Skip to main content
Glama
tm-core.ts6.48 kB
/** * @fileoverview TmCore - Unified facade for all Task Master functionality * This is the ONLY entry point for using tm-core */ import path from 'node:path'; import { AuthDomain } from './modules/auth/auth-domain.js'; import { ConfigDomain } from './modules/config/config-domain.js'; import { ConfigManager } from './modules/config/managers/config-manager.js'; import { GitDomain } from './modules/git/git-domain.js'; import { IntegrationDomain } from './modules/integration/integration-domain.js'; import { TasksDomain } from './modules/tasks/tasks-domain.js'; import { WorkflowDomain } from './modules/workflow/workflow-domain.js'; import { ERROR_CODES, TaskMasterError } from './common/errors/task-master-error.js'; import type { IConfiguration } from './common/interfaces/configuration.interface.js'; import { type Logger, type LoggerConfig, createLogger } from './common/logger/index.js'; /** * Options for creating TmCore instance */ export interface TmCoreOptions { /** Absolute path to project root */ projectPath: string; /** Optional configuration overrides */ configuration?: Partial<IConfiguration>; /** Optional logger configuration for MCP integration and debugging */ loggerConfig?: LoggerConfig; } /** * TmCore - Unified facade providing access to all Task Master domains * * @example Basic usage * ```typescript * const tmcore = await createTmCore({ projectPath: process.cwd() }); * * // Access any domain * await tmcore.auth.authenticateWithOAuth(); * const tasks = await tmcore.tasks.list(); * await tmcore.workflow.start({ taskId: '1' }); * await tmcore.git.commit('feat: add feature'); * const modelConfig = tmcore.config.getModelConfig(); * await tmcore.integration.exportTasks({ ... }); * ``` * * @example MCP integration with logging * ```typescript * import { LogLevel } from '@tm/core/logger'; * * // In MCP tool execute function * async function execute(args, log) { * const tmcore = await createTmCore({ * projectPath: args.projectRoot, * loggerConfig: { * level: LogLevel.INFO, * mcpMode: true, * logCallback: log // MCP log function * } * }); * * // All internal logging will now be sent to MCP * const tasks = await tmcore.tasks.list(); * * // You can also log custom messages * tmcore.logger.info('Operation completed'); * } * ``` */ export class TmCore { // Core infrastructure private readonly _projectPath: string; private _configManager!: ConfigManager; private _logger!: Logger; // Private writable properties private _tasks!: TasksDomain; private _auth!: AuthDomain; private _workflow!: WorkflowDomain; private _git!: GitDomain; private _config!: ConfigDomain; private _integration!: IntegrationDomain; // Public readonly getters get tasks(): TasksDomain { return this._tasks; } get auth(): AuthDomain { return this._auth; } get workflow(): WorkflowDomain { return this._workflow; } get git(): GitDomain { return this._git; } get config(): ConfigDomain { return this._config; } get integration(): IntegrationDomain { return this._integration; } get logger(): Logger { return this._logger; } /** * Create and initialize a new TmCore instance * This is the ONLY way to create TmCore * * @param options - Configuration options * @returns Fully initialized TmCore instance */ static async create(options: TmCoreOptions): Promise<TmCore> { const instance = new TmCore(options); await instance.initialize(); return instance; } private _options: TmCoreOptions; /** * Private constructor - use TmCore.create() instead * This ensures TmCore is always properly initialized */ private constructor(options: TmCoreOptions) { if (!options.projectPath) { throw new TaskMasterError( 'Project path is required', ERROR_CODES.MISSING_CONFIGURATION ); } // Validate that projectPath is absolute if (!path.isAbsolute(options.projectPath)) { throw new TaskMasterError( `Project path must be an absolute path, received: "${options.projectPath}"`, ERROR_CODES.INVALID_INPUT ); } // Normalize the path this._projectPath = path.resolve(options.projectPath); this._options = options; // Domain facades will be initialized in initialize() } /** * Initialize the TmCore instance * Private - only called by the factory method */ private async initialize(): Promise<void> { try { // Initialize logger first (before anything else that might log) this._logger = createLogger(this._options.loggerConfig); // Create config manager this._configManager = await ConfigManager.create(this._projectPath); // Apply configuration overrides if provided if (this._options.configuration) { await this._configManager.updateConfig(this._options.configuration); } // Initialize domain facades this._auth = new AuthDomain(); this._tasks = new TasksDomain(this._configManager, this._auth); this._workflow = new WorkflowDomain(this._configManager); this._git = new GitDomain(this._projectPath); this._config = new ConfigDomain(this._configManager); this._integration = new IntegrationDomain(this._configManager); // Initialize domains that need async setup await this._tasks.initialize(); // Wire up cross-domain dependencies // WorkflowDomain needs TasksDomain for status updates this._workflow.setTasksDomain(this._tasks); // Log successful initialization this._logger.info('TmCore initialized successfully'); } catch (error) { // Log error if logger is available if (this._logger) { this._logger.error('Failed to initialize TmCore:', error); } throw new TaskMasterError( 'Failed to initialize TmCore', ERROR_CODES.INTERNAL_ERROR, { operation: 'initialize' }, error as Error ); } } /** * Get project root path */ get projectPath(): string { return this._projectPath; } /** * Close and cleanup resources * Releases file locks and other storage resources * Should be called when done using TmCore, especially in tests */ async close(): Promise<void> { if (this._tasks) { await this._tasks.close(); } } } /** * Factory function to create a new TmCore instance * This is the recommended way to create TmCore * * @param options - Configuration options * @returns Fully initialized TmCore instance */ export async function createTmCore(options: TmCoreOptions): Promise<TmCore> { return TmCore.create(options); }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/eyaltoledano/claude-task-master'

If you have feedback or need assistance with the MCP directory API, please join our Discord server