takt/src/config/projectConfig.ts
2026-01-25 15:16:27 +09:00

114 lines
3.0 KiB
TypeScript

/**
* Project-level configuration management
*
* Manages .takt/config.yaml for project-specific settings.
*/
import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'node:fs';
import { join, resolve } from 'node:path';
import { parse, stringify } from 'yaml';
/** Project configuration stored in .takt/config.yaml */
export interface ProjectLocalConfig {
/** Current workflow name */
workflow?: string;
/** Auto-approve all permissions in this project */
sacrificeMode?: boolean;
/** Verbose output mode */
verbose?: boolean;
/** Custom settings */
[key: string]: unknown;
}
/** Default project configuration */
const DEFAULT_PROJECT_CONFIG: ProjectLocalConfig = {
workflow: 'default',
};
/**
* Get project takt config directory (.takt in project)
* Note: Defined locally to avoid circular dependency with paths.ts
*/
function getConfigDir(projectDir: string): string {
return join(resolve(projectDir), '.takt');
}
/**
* Get project config file path
* Note: Defined locally to avoid circular dependency with paths.ts
*/
function getConfigPath(projectDir: string): string {
return join(getConfigDir(projectDir), 'config.yaml');
}
/**
* Load project configuration from .takt/config.yaml
*/
export function loadProjectConfig(projectDir: string): ProjectLocalConfig {
const configPath = getConfigPath(projectDir);
if (!existsSync(configPath)) {
return { ...DEFAULT_PROJECT_CONFIG };
}
try {
const content = readFileSync(configPath, 'utf-8');
const parsed = parse(content) as ProjectLocalConfig | null;
return { ...DEFAULT_PROJECT_CONFIG, ...parsed };
} catch {
return { ...DEFAULT_PROJECT_CONFIG };
}
}
/**
* Save project configuration to .takt/config.yaml
*/
export function saveProjectConfig(projectDir: string, config: ProjectLocalConfig): void {
const configDir = getConfigDir(projectDir);
const configPath = getConfigPath(projectDir);
// Ensure directory exists
if (!existsSync(configDir)) {
mkdirSync(configDir, { recursive: true });
}
const content = stringify(config, { indent: 2 });
writeFileSync(configPath, content, 'utf-8');
}
/**
* Update a single field in project configuration
*/
export function updateProjectConfig<K extends keyof ProjectLocalConfig>(
projectDir: string,
key: K,
value: ProjectLocalConfig[K]
): void {
const config = loadProjectConfig(projectDir);
config[key] = value;
saveProjectConfig(projectDir, config);
}
/**
* Get current workflow from project config
*/
export function getCurrentWorkflow(projectDir: string): string {
const config = loadProjectConfig(projectDir);
return config.workflow || 'default';
}
/**
* Set current workflow in project config
*/
export function setCurrentWorkflow(projectDir: string, workflow: string): void {
updateProjectConfig(projectDir, 'workflow', workflow);
}
/**
* Get verbose mode from project config
*/
export function isVerboseMode(projectDir: string): boolean {
const config = loadProjectConfig(projectDir);
return config.verbose === true;
}