feat: create tm-core and apps/cli (#1093)
- add typescript - add npm workspaces
This commit is contained in:
124
packages/tm-core/src/config/services/config-loader.service.ts
Normal file
124
packages/tm-core/src/config/services/config-loader.service.ts
Normal file
@@ -0,0 +1,124 @@
|
||||
/**
|
||||
* @fileoverview Configuration Loader Service
|
||||
* Responsible for loading configuration from various file sources
|
||||
*/
|
||||
|
||||
import { promises as fs } from 'node:fs';
|
||||
import path from 'node:path';
|
||||
import type { PartialConfiguration } from '../../interfaces/configuration.interface.js';
|
||||
import { DEFAULT_CONFIG_VALUES } from '../../interfaces/configuration.interface.js';
|
||||
import {
|
||||
ERROR_CODES,
|
||||
TaskMasterError
|
||||
} from '../../errors/task-master-error.js';
|
||||
|
||||
/**
|
||||
* ConfigLoader handles loading configuration from files
|
||||
* Single responsibility: File-based configuration loading
|
||||
*/
|
||||
export class ConfigLoader {
|
||||
private localConfigPath: string;
|
||||
private globalConfigPath: string;
|
||||
|
||||
constructor(projectRoot: string) {
|
||||
this.localConfigPath = path.join(projectRoot, '.taskmaster', 'config.json');
|
||||
this.globalConfigPath = path.join(
|
||||
process.env.HOME || '',
|
||||
'.taskmaster',
|
||||
'config.json'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get default configuration values
|
||||
*/
|
||||
getDefaultConfig(): PartialConfiguration {
|
||||
return {
|
||||
models: {
|
||||
main: DEFAULT_CONFIG_VALUES.MODELS.MAIN,
|
||||
fallback: DEFAULT_CONFIG_VALUES.MODELS.FALLBACK
|
||||
},
|
||||
storage: {
|
||||
type: DEFAULT_CONFIG_VALUES.STORAGE.TYPE,
|
||||
encoding: DEFAULT_CONFIG_VALUES.STORAGE.ENCODING,
|
||||
enableBackup: false,
|
||||
maxBackups: DEFAULT_CONFIG_VALUES.STORAGE.MAX_BACKUPS,
|
||||
enableCompression: false,
|
||||
atomicOperations: true
|
||||
},
|
||||
version: DEFAULT_CONFIG_VALUES.VERSION
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Load local project configuration
|
||||
*/
|
||||
async loadLocalConfig(): Promise<PartialConfiguration | null> {
|
||||
try {
|
||||
const configData = await fs.readFile(this.localConfigPath, 'utf-8');
|
||||
return JSON.parse(configData);
|
||||
} catch (error: any) {
|
||||
if (error.code === 'ENOENT') {
|
||||
// File doesn't exist, return null
|
||||
console.debug('No local config.json found, using defaults');
|
||||
return null;
|
||||
}
|
||||
throw new TaskMasterError(
|
||||
'Failed to load local configuration',
|
||||
ERROR_CODES.CONFIG_ERROR,
|
||||
{ configPath: this.localConfigPath },
|
||||
error
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load global user configuration
|
||||
* @future-implementation Full implementation pending
|
||||
*/
|
||||
async loadGlobalConfig(): Promise<PartialConfiguration | null> {
|
||||
// TODO: Implement in future PR
|
||||
// For now, return null to indicate no global config
|
||||
return null;
|
||||
|
||||
// Future implementation:
|
||||
// try {
|
||||
// const configData = await fs.readFile(this.globalConfigPath, 'utf-8');
|
||||
// return JSON.parse(configData);
|
||||
// } catch (error: any) {
|
||||
// if (error.code === 'ENOENT') {
|
||||
// return null;
|
||||
// }
|
||||
// throw new TaskMasterError(
|
||||
// 'Failed to load global configuration',
|
||||
// ERROR_CODES.CONFIG_ERROR,
|
||||
// { configPath: this.globalConfigPath },
|
||||
// error
|
||||
// );
|
||||
// }
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if local config exists
|
||||
*/
|
||||
async hasLocalConfig(): Promise<boolean> {
|
||||
try {
|
||||
await fs.access(this.localConfigPath);
|
||||
return true;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if global config exists
|
||||
*/
|
||||
async hasGlobalConfig(): Promise<boolean> {
|
||||
try {
|
||||
await fs.access(this.globalConfigPath);
|
||||
return true;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user