refactor: centralize BMAD_FOLDER_NAME constant in path-utils

This commit is contained in:
Davor Racić 2026-02-01 12:24:09 +01:00
parent 2ef410c726
commit 8ed36d9f0d
6 changed files with 22 additions and 18 deletions

View File

@ -17,9 +17,7 @@ const { ManifestGenerator } = require('./manifest-generator');
const { IdeConfigManager } = require('./ide-config-manager'); const { IdeConfigManager } = require('./ide-config-manager');
const { CustomHandler } = require('../custom/handler'); const { CustomHandler } = require('../custom/handler');
const prompts = require('../../../lib/prompts'); const prompts = require('../../../lib/prompts');
const { BMAD_FOLDER_NAME } = require('../ide/shared/path-utils');
// BMAD installation folder name - this is constant and should never change
const BMAD_FOLDER_NAME = '_bmad';
class Installer { class Installer {
constructor() { constructor() {

View File

@ -3,6 +3,7 @@ const fs = require('fs-extra');
const chalk = require('chalk'); const chalk = require('chalk');
const { XmlHandler } = require('../../../lib/xml-handler'); const { XmlHandler } = require('../../../lib/xml-handler');
const { getSourcePath } = require('../../../lib/project-root'); const { getSourcePath } = require('../../../lib/project-root');
const { BMAD_FOLDER_NAME } = require('./shared/path-utils');
/** /**
* Base class for IDE-specific setup * Base class for IDE-specific setup
@ -18,7 +19,7 @@ class BaseIdeSetup {
this.configFile = null; // Override in subclasses when detection is file-based this.configFile = null; // Override in subclasses when detection is file-based
this.detectionPaths = []; // Additional paths that indicate the IDE is configured this.detectionPaths = []; // Additional paths that indicate the IDE is configured
this.xmlHandler = new XmlHandler(); this.xmlHandler = new XmlHandler();
this.bmadFolderName = '_bmad'; // Default, can be overridden this.bmadFolderName = BMAD_FOLDER_NAME; // Default, can be overridden
} }
/** /**
@ -57,7 +58,7 @@ class BaseIdeSetup {
if (this.configDir) { if (this.configDir) {
const configPath = path.join(projectDir, this.configDir); const configPath = path.join(projectDir, this.configDir);
if (await fs.pathExists(configPath)) { if (await fs.pathExists(configPath)) {
const bmadRulesPath = path.join(configPath, 'bmad'); const bmadRulesPath = path.join(configPath, BMAD_FOLDER_NAME);
if (await fs.pathExists(bmadRulesPath)) { if (await fs.pathExists(bmadRulesPath)) {
await fs.remove(bmadRulesPath); await fs.remove(bmadRulesPath);
console.log(chalk.dim(`Removed ${this.name} BMAD configuration`)); console.log(chalk.dim(`Removed ${this.name} BMAD configuration`));

View File

@ -1,14 +1,14 @@
const path = require('node:path'); const path = require('node:path');
const fs = require('fs-extra'); const fs = require('fs-extra');
const chalk = require('chalk'); const chalk = require('chalk');
const { toColonPath, toDashPath, customAgentColonName, customAgentDashName } = require('./path-utils'); const { toColonPath, toDashPath, customAgentColonName, customAgentDashName, BMAD_FOLDER_NAME } = require('./path-utils');
/** /**
* Generates launcher command files for each agent * Generates launcher command files for each agent
* Similar to WorkflowCommandGenerator but for agents * Similar to WorkflowCommandGenerator but for agents
*/ */
class AgentCommandGenerator { class AgentCommandGenerator {
constructor(bmadFolderName = '_bmad') { constructor(bmadFolderName = BMAD_FOLDER_NAME) {
this.templatePath = path.join(__dirname, '../templates/agent-command-template.md'); this.templatePath = path.join(__dirname, '../templates/agent-command-template.md');
this.bmadFolderName = bmadFolderName; this.bmadFolderName = bmadFolderName;
} }

View File

@ -18,6 +18,9 @@
const TYPE_SEGMENTS = ['workflows', 'tasks', 'tools']; const TYPE_SEGMENTS = ['workflows', 'tasks', 'tools'];
const AGENT_SEGMENT = 'agents'; const AGENT_SEGMENT = 'agents';
// BMAD installation folder name - centralized constant for all installers
const BMAD_FOLDER_NAME = '_bmad';
/** /**
* Convert hierarchical path to flat dash-separated name (NEW STANDARD) * Convert hierarchical path to flat dash-separated name (NEW STANDARD)
* Converts: 'bmm', 'agents', 'pm' 'bmad-agent-bmm-pm.md' * Converts: 'bmm', 'agents', 'pm' 'bmad-agent-bmm-pm.md'
@ -292,4 +295,5 @@ module.exports = {
TYPE_SEGMENTS, TYPE_SEGMENTS,
AGENT_SEGMENT, AGENT_SEGMENT,
BMAD_FOLDER_NAME,
}; };

View File

@ -2,20 +2,20 @@ const path = require('node:path');
const fs = require('fs-extra'); const fs = require('fs-extra');
const csv = require('csv-parse/sync'); const csv = require('csv-parse/sync');
const chalk = require('chalk'); const chalk = require('chalk');
const { toColonName, toColonPath, toDashPath } = require('./path-utils'); const { toColonName, toColonPath, toDashPath, BMAD_FOLDER_NAME } = require('./path-utils');
/** /**
* Generates command files for standalone tasks and tools * Generates command files for standalone tasks and tools
*/ */
class TaskToolCommandGenerator { class TaskToolCommandGenerator {
/** /**
* @param {string} bmadFolderName - Name of the BMAD folder for template rendering (default: 'bmad') * @param {string} bmadFolderName - Name of the BMAD folder for template rendering (default: '_bmad')
* Note: This parameter is accepted for API consistency with AgentCommandGenerator and * Note: This parameter is accepted for API consistency with AgentCommandGenerator and
* WorkflowCommandGenerator, but is not used for path stripping. The manifest always stores * WorkflowCommandGenerator, but is not used for path stripping. The manifest always stores
* filesystem paths with '_bmad/' prefix (the actual folder name), while bmadFolderName is * filesystem paths with '_bmad/' prefix (the actual folder name), while bmadFolderName is
* used for template placeholder rendering ({{bmadFolderName}}). * used for template placeholder rendering ({{bmadFolderName}}).
*/ */
constructor(bmadFolderName = '_bmad') { constructor(bmadFolderName = BMAD_FOLDER_NAME) {
this.bmadFolderName = bmadFolderName; this.bmadFolderName = bmadFolderName;
} }
@ -33,13 +33,14 @@ class TaskToolCommandGenerator {
const standaloneTools = tools ? tools.filter((t) => t.standalone === 'true' || t.standalone === true) : []; const standaloneTools = tools ? tools.filter((t) => t.standalone === 'true' || t.standalone === true) : [];
const artifacts = []; const artifacts = [];
const bmadPrefix = `${BMAD_FOLDER_NAME}/`;
// Collect task artifacts // Collect task artifacts
for (const task of standaloneTasks) { for (const task of standaloneTasks) {
let taskPath = (task.path || '').replaceAll('\\', '/'); let taskPath = (task.path || '').replaceAll('\\', '/');
// Remove _bmad/ prefix if present to get relative path within bmad folder // Remove _bmad/ prefix if present to get relative path within bmad folder
if (taskPath.startsWith('_bmad/')) { if (taskPath.startsWith(bmadPrefix)) {
taskPath = taskPath.slice(6); // Remove '_bmad/' taskPath = taskPath.slice(bmadPrefix.length);
} }
const taskExt = path.extname(taskPath) || '.md'; const taskExt = path.extname(taskPath) || '.md';
@ -59,8 +60,8 @@ class TaskToolCommandGenerator {
for (const tool of standaloneTools) { for (const tool of standaloneTools) {
let toolPath = (tool.path || '').replaceAll('\\', '/'); let toolPath = (tool.path || '').replaceAll('\\', '/');
// Remove _bmad/ prefix if present to get relative path within bmad folder // Remove _bmad/ prefix if present to get relative path within bmad folder
if (toolPath.startsWith('_bmad/')) { if (toolPath.startsWith(bmadPrefix)) {
toolPath = toolPath.slice(6); // Remove '_bmad/' toolPath = toolPath.slice(bmadPrefix.length);
} }
const toolExt = path.extname(toolPath) || '.md'; const toolExt = path.extname(toolPath) || '.md';
@ -159,9 +160,9 @@ class TaskToolCommandGenerator {
if (bmadMatch) { if (bmadMatch) {
// Found /_bmad/ or /bmad/ - use relative path after it // Found /_bmad/ or /bmad/ - use relative path after it
itemPath = `{project-root}/${this.bmadFolderName}/${bmadMatch[1]}`; itemPath = `{project-root}/${this.bmadFolderName}/${bmadMatch[1]}`;
} else if (itemPath.startsWith('_bmad/')) { } else if (itemPath.startsWith(`${BMAD_FOLDER_NAME}/`)) {
// Relative path starting with _bmad/ // Relative path starting with _bmad/
itemPath = `{project-root}/${this.bmadFolderName}/${itemPath.slice(6)}`; itemPath = `{project-root}/${this.bmadFolderName}/${itemPath.slice(BMAD_FOLDER_NAME.length + 1)}`;
} else if (itemPath.startsWith('bmad/')) { } else if (itemPath.startsWith('bmad/')) {
// Relative path starting with bmad/ // Relative path starting with bmad/
itemPath = `{project-root}/${this.bmadFolderName}/${itemPath.slice(5)}`; itemPath = `{project-root}/${this.bmadFolderName}/${itemPath.slice(5)}`;

View File

@ -2,13 +2,13 @@ const path = require('node:path');
const fs = require('fs-extra'); const fs = require('fs-extra');
const csv = require('csv-parse/sync'); const csv = require('csv-parse/sync');
const chalk = require('chalk'); const chalk = require('chalk');
const { toColonPath, toDashPath, customAgentColonName, customAgentDashName } = require('./path-utils'); const { toColonPath, toDashPath, customAgentColonName, customAgentDashName, BMAD_FOLDER_NAME } = require('./path-utils');
/** /**
* Generates command files for each workflow in the manifest * Generates command files for each workflow in the manifest
*/ */
class WorkflowCommandGenerator { class WorkflowCommandGenerator {
constructor(bmadFolderName = '_bmad') { constructor(bmadFolderName = BMAD_FOLDER_NAME) {
this.templatePath = path.join(__dirname, '../templates/workflow-command-template.md'); this.templatePath = path.join(__dirname, '../templates/workflow-command-template.md');
this.bmadFolderName = bmadFolderName; this.bmadFolderName = bmadFolderName;
} }