refactor(installer): move discoverCustomModulePaths into CustomModules

Rename to CustomModules.discoverPaths() and move from installer.js
into custom-modules.js where it belongs.
This commit is contained in:
Alex Verkhovsky 2026-03-21 04:43:58 -06:00
parent ea8c076e29
commit a7beab59b9
2 changed files with 75 additions and 70 deletions

View File

@ -59,7 +59,7 @@ class Installer {
const moduleConfigs = await this._collectConfigs(config, paths);
// Custom module path discovery (will move to its own phase later)
const customModulePaths = await this._discoverCustomModulePaths(config, paths);
const customModulePaths = await this.customModules.discoverPaths(config, paths);
// Wire configs into managers
this.customModules.setPaths(customModulePaths);
@ -898,7 +898,7 @@ class Installer {
/**
* Collect configurations for official modules (core + selected).
* Custom module configs are handled separately in _discoverCustomModulePaths.
* Custom module configs are handled separately in CustomModules.discoverPaths.
*/
async _collectConfigs(config, paths) {
// Seed core config if pre-collected from interactive UI
@ -924,74 +924,6 @@ class Installer {
});
}
/**
* Discover custom module source paths from all available sources.
* This is a temporary home will move to a dedicated custom module phase.
*/
async _discoverCustomModulePaths(config, paths) {
const customModulePaths = new Map();
if (config._quickUpdate) {
if (config._customModuleSources) {
for (const [moduleId, customInfo] of config._customModuleSources) {
customModulePaths.set(moduleId, customInfo.sourcePath);
}
}
return customModulePaths;
}
// From manifest (regular updates)
if (config._isUpdate && config._existingInstall && config._existingInstall.customModules) {
for (const customModule of config._existingInstall.customModules) {
let absoluteSourcePath = customModule.sourcePath;
if (absoluteSourcePath && absoluteSourcePath.startsWith('_config')) {
absoluteSourcePath = path.join(paths.bmadDir, absoluteSourcePath);
} else if (!absoluteSourcePath && customModule.relativePath) {
absoluteSourcePath = path.resolve(paths.projectRoot, customModule.relativePath);
} else if (absoluteSourcePath && !path.isAbsolute(absoluteSourcePath)) {
absoluteSourcePath = path.resolve(absoluteSourcePath);
}
if (absoluteSourcePath) {
customModulePaths.set(customModule.id, absoluteSourcePath);
}
}
}
// From UI: selectedFiles
if (config.customContent && config.customContent.selected && config.customContent.selectedFiles) {
const customHandler = new CustomHandler();
for (const customFile of config.customContent.selectedFiles) {
const customInfo = await customHandler.getCustomInfo(customFile, paths.projectRoot);
if (customInfo && customInfo.id) {
customModulePaths.set(customInfo.id, customInfo.path);
}
}
}
// From UI: sources
if (config.customContent && config.customContent.sources) {
for (const source of config.customContent.sources) {
customModulePaths.set(source.id, source.path);
}
}
// From UI: cachedModules
if (config.customContent && config.customContent.cachedModules) {
const selectedCachedIds = config.customContent.selectedCachedModules || [];
const shouldIncludeAll = selectedCachedIds.length === 0 && config.customContent.selected;
for (const cachedModule of config.customContent.cachedModules) {
if (cachedModule.id && cachedModule.cachePath && (shouldIncludeAll || selectedCachedIds.includes(cachedModule.id))) {
customModulePaths.set(cachedModule.id, cachedModule.cachePath);
}
}
}
return customModulePaths;
}
/**
* Install official (non-custom) modules.
* @param {Object} config - Installation configuration

View File

@ -1,3 +1,6 @@
const path = require('node:path');
const { CustomHandler } = require('../custom-handler');
class CustomModules {
constructor() {
this.paths = new Map();
@ -18,6 +21,76 @@ class CustomModules {
set(moduleId, sourcePath) {
this.paths.set(moduleId, sourcePath);
}
/**
* Discover custom module source paths from all available sources.
* @param {Object} config - Installation configuration
* @param {Object} paths - InstallPaths instance
* @returns {Map<string, string>} Map of module ID to source path
*/
async discoverPaths(config, paths) {
const result = new Map();
if (config._quickUpdate) {
if (config._customModuleSources) {
for (const [moduleId, customInfo] of config._customModuleSources) {
result.set(moduleId, customInfo.sourcePath);
}
}
return result;
}
// From manifest (regular updates)
if (config._isUpdate && config._existingInstall && config._existingInstall.customModules) {
for (const customModule of config._existingInstall.customModules) {
let absoluteSourcePath = customModule.sourcePath;
if (absoluteSourcePath && absoluteSourcePath.startsWith('_config')) {
absoluteSourcePath = path.join(paths.bmadDir, absoluteSourcePath);
} else if (!absoluteSourcePath && customModule.relativePath) {
absoluteSourcePath = path.resolve(paths.projectRoot, customModule.relativePath);
} else if (absoluteSourcePath && !path.isAbsolute(absoluteSourcePath)) {
absoluteSourcePath = path.resolve(absoluteSourcePath);
}
if (absoluteSourcePath) {
result.set(customModule.id, absoluteSourcePath);
}
}
}
// From UI: selectedFiles
if (config.customContent && config.customContent.selected && config.customContent.selectedFiles) {
const customHandler = new CustomHandler();
for (const customFile of config.customContent.selectedFiles) {
const customInfo = await customHandler.getCustomInfo(customFile, paths.projectRoot);
if (customInfo && customInfo.id) {
result.set(customInfo.id, customInfo.path);
}
}
}
// From UI: sources
if (config.customContent && config.customContent.sources) {
for (const source of config.customContent.sources) {
result.set(source.id, source.path);
}
}
// From UI: cachedModules
if (config.customContent && config.customContent.cachedModules) {
const selectedCachedIds = config.customContent.selectedCachedModules || [];
const shouldIncludeAll = selectedCachedIds.length === 0 && config.customContent.selected;
for (const cachedModule of config.customContent.cachedModules) {
if (cachedModule.id && cachedModule.cachePath && (shouldIncludeAll || selectedCachedIds.includes(cachedModule.id))) {
result.set(cachedModule.id, cachedModule.cachePath);
}
}
}
return result;
}
}
module.exports = { CustomModules };