feat: Add .taskmaster directory (#619)
This commit is contained in:
@@ -3,6 +3,8 @@ import path from 'path';
|
||||
import chalk from 'chalk';
|
||||
import { fileURLToPath } from 'url';
|
||||
import { log, findProjectRoot, resolveEnvVariable } from './utils.js';
|
||||
import { LEGACY_CONFIG_FILE } from '../../src/constants/paths.js';
|
||||
import { findConfigPath } from '../../src/utils/path-utils.js';
|
||||
|
||||
// Calculate __dirname in ESM
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
@@ -27,12 +29,10 @@ try {
|
||||
process.exit(1); // Exit if models can't be loaded
|
||||
}
|
||||
|
||||
const CONFIG_FILE_NAME = '.taskmasterconfig';
|
||||
|
||||
// Define valid providers dynamically from the loaded MODEL_MAP
|
||||
const VALID_PROVIDERS = Object.keys(MODEL_MAP || {});
|
||||
|
||||
// Default configuration values (used if .taskmasterconfig is missing or incomplete)
|
||||
// Default configuration values (used if config file is missing or incomplete)
|
||||
const DEFAULTS = {
|
||||
models: {
|
||||
main: {
|
||||
@@ -96,13 +96,15 @@ function _loadAndValidateConfig(explicitRoot = null) {
|
||||
}
|
||||
// ---> End find project root logic <---
|
||||
|
||||
// --- Proceed with loading from the determined rootToUse ---
|
||||
const configPath = path.join(rootToUse, CONFIG_FILE_NAME);
|
||||
// --- Find configuration file using centralized path utility ---
|
||||
const configPath = findConfigPath(null, { projectRoot: rootToUse });
|
||||
let config = { ...defaults }; // Start with a deep copy of defaults
|
||||
let configExists = false;
|
||||
|
||||
if (fs.existsSync(configPath)) {
|
||||
if (configPath) {
|
||||
configExists = true;
|
||||
const isLegacy = configPath.endsWith(LEGACY_CONFIG_FILE);
|
||||
|
||||
try {
|
||||
const rawData = fs.readFileSync(configPath, 'utf-8');
|
||||
const parsedConfig = JSON.parse(rawData);
|
||||
@@ -125,6 +127,15 @@ function _loadAndValidateConfig(explicitRoot = null) {
|
||||
};
|
||||
configSource = `file (${configPath})`; // Update source info
|
||||
|
||||
// Issue deprecation warning if using legacy config file
|
||||
if (isLegacy) {
|
||||
console.warn(
|
||||
chalk.yellow(
|
||||
`⚠️ DEPRECATION WARNING: Found configuration in legacy location '${configPath}'. Please migrate to .taskmaster/config.json. Run 'task-master migrate' to automatically migrate your project.`
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// --- Validation (Warn if file content is invalid) ---
|
||||
// Use log.warn for consistency
|
||||
if (!validateProvider(config.models.main.provider)) {
|
||||
@@ -171,19 +182,19 @@ function _loadAndValidateConfig(explicitRoot = null) {
|
||||
// Only warn if an explicit root was *expected*.
|
||||
console.warn(
|
||||
chalk.yellow(
|
||||
`Warning: ${CONFIG_FILE_NAME} not found at provided project root (${explicitRoot}). Using default configuration. Run 'task-master models --setup' to configure.`
|
||||
`Warning: Configuration file not found at provided project root (${explicitRoot}). Using default configuration. Run 'task-master models --setup' to configure.`
|
||||
)
|
||||
);
|
||||
} else {
|
||||
console.warn(
|
||||
chalk.yellow(
|
||||
`Warning: ${CONFIG_FILE_NAME} not found at derived root (${rootToUse}). Using defaults.`
|
||||
`Warning: Configuration file not found at derived root (${rootToUse}). Using defaults.`
|
||||
)
|
||||
);
|
||||
}
|
||||
// Keep config as defaults
|
||||
config = { ...defaults };
|
||||
configSource = `defaults (file not found at ${configPath})`;
|
||||
configSource = `defaults (no config file found at ${rootToUse})`;
|
||||
}
|
||||
|
||||
return config;
|
||||
@@ -342,13 +353,13 @@ function getDefaultSubtasks(explicitRoot = null) {
|
||||
// Directly return value from config, ensure integer
|
||||
const val = getGlobalConfig(explicitRoot).defaultSubtasks;
|
||||
const parsedVal = parseInt(val, 10);
|
||||
return isNaN(parsedVal) ? DEFAULTS.global.defaultSubtasks : parsedVal;
|
||||
return Number.isNaN(parsedVal) ? DEFAULTS.global.defaultSubtasks : parsedVal;
|
||||
}
|
||||
|
||||
function getDefaultNumTasks(explicitRoot = null) {
|
||||
const val = getGlobalConfig(explicitRoot).defaultNumTasks;
|
||||
const parsedVal = parseInt(val, 10);
|
||||
return isNaN(parsedVal) ? DEFAULTS.global.defaultNumTasks : parsedVal;
|
||||
return Number.isNaN(parsedVal) ? DEFAULTS.global.defaultNumTasks : parsedVal;
|
||||
}
|
||||
|
||||
function getDefaultPriority(explicitRoot = null) {
|
||||
@@ -658,12 +669,16 @@ function writeConfig(config, explicitRoot = null) {
|
||||
}
|
||||
// ---> End determine root path logic <---
|
||||
|
||||
const configPath =
|
||||
path.basename(rootPath) === CONFIG_FILE_NAME
|
||||
? rootPath
|
||||
: path.join(rootPath, CONFIG_FILE_NAME);
|
||||
// Use new config location: .taskmaster/config.json
|
||||
const taskmasterDir = path.join(rootPath, '.taskmaster');
|
||||
const configPath = path.join(taskmasterDir, 'config.json');
|
||||
|
||||
try {
|
||||
// Ensure .taskmaster directory exists
|
||||
if (!fs.existsSync(taskmasterDir)) {
|
||||
fs.mkdirSync(taskmasterDir, { recursive: true });
|
||||
}
|
||||
|
||||
fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
|
||||
loadedConfig = config; // Update the cache after successful write
|
||||
return true;
|
||||
@@ -678,25 +693,12 @@ function writeConfig(config, explicitRoot = null) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the .taskmasterconfig file exists at the project root
|
||||
* Checks if a configuration file exists at the project root (new or legacy location)
|
||||
* @param {string|null} explicitRoot - Optional explicit path to the project root
|
||||
* @returns {boolean} True if the file exists, false otherwise
|
||||
*/
|
||||
function isConfigFilePresent(explicitRoot = null) {
|
||||
// ---> Determine root path reliably <---
|
||||
let rootPath = explicitRoot;
|
||||
if (explicitRoot === null || explicitRoot === undefined) {
|
||||
// Logic matching _loadAndValidateConfig
|
||||
const foundRoot = findProjectRoot(); // *** Explicitly call findProjectRoot ***
|
||||
if (!foundRoot) {
|
||||
return false; // Cannot check if root doesn't exist
|
||||
}
|
||||
rootPath = foundRoot;
|
||||
}
|
||||
// ---> End determine root path logic <---
|
||||
|
||||
const configPath = path.join(rootPath, CONFIG_FILE_NAME);
|
||||
return fs.existsSync(configPath);
|
||||
return findConfigPath(null, { projectRoot: explicitRoot }) !== null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user