refactor(installer): extract _buildConfig method with hasCoreConfig()

Move config normalization into _buildConfig(originalConfig) so the gate
logic is a named, testable method. Add hasCoreConfig() on the returned
config object to replace the repeated coreConfig && Object.keys pattern.
This commit is contained in:
Alex Verkhovsky 2026-03-21 05:24:54 -06:00
parent 68f723d427
commit e41cc1f822
1 changed files with 13 additions and 9 deletions

View File

@ -41,15 +41,13 @@ class Installer {
* @param {string[]} config.modules - Modules to install (including 'core') * @param {string[]} config.modules - Modules to install (including 'core')
* @param {string[]} config.ides - IDEs to configure * @param {string[]} config.ides - IDEs to configure
*/ */
async install(originalConfig) { _buildConfig(originalConfig) {
// Build a normalized config with explicit fields — no opaque spread
// Clean config for the official module install path
const modules = [...(originalConfig.modules || [])]; const modules = [...(originalConfig.modules || [])];
if (originalConfig.installCore && !modules.includes('core')) { if (originalConfig.installCore && !modules.includes('core')) {
modules.unshift('core'); modules.unshift('core');
} }
const config = { return {
directory: originalConfig.directory, directory: originalConfig.directory,
modules, modules,
ides: originalConfig.skipIde ? [] : [...(originalConfig.ides || [])], ides: originalConfig.skipIde ? [] : [...(originalConfig.ides || [])],
@ -58,14 +56,20 @@ class Installer {
force: originalConfig.force || false, force: originalConfig.force || false,
actionType: originalConfig.actionType, actionType: originalConfig.actionType,
coreConfig: originalConfig.coreConfig || {}, coreConfig: originalConfig.coreConfig || {},
hasCoreConfig() {
return this.coreConfig && Object.keys(this.coreConfig).length > 0;
},
}; };
}
// Everything — custom modules, quick-update state, the whole mess async install(originalConfig) {
const config = this._buildConfig(originalConfig);
// Everything else — custom modules, quick-update state, the whole mess
const customConfig = { ...originalConfig }; const customConfig = { ...originalConfig };
// if core config isn't collected, we haven't run the UI -> display logo/version // if core config isn't collected, we haven't run the UI -> display logo/version
const hasCoreConfig = config.coreConfig && Object.keys(config.coreConfig).length > 0; if (!config.hasCoreConfig()) {
if (!hasCoreConfig) {
await CLIUtils.displayLogo(); await CLIUtils.displayLogo();
} }
@ -869,7 +873,8 @@ class Installer {
*/ */
async _collectConfigs(customConfig, paths) { async _collectConfigs(customConfig, paths) {
// Seed core config if pre-collected from interactive UI // Seed core config if pre-collected from interactive UI
if (customConfig.coreConfig && Object.keys(customConfig.coreConfig).length > 0) { const hasCoreConfig = customConfig.coreConfig && Object.keys(customConfig.coreConfig).length > 0;
if (hasCoreConfig) {
this.configCollector.collectedConfig.core = customConfig.coreConfig; this.configCollector.collectedConfig.core = customConfig.coreConfig;
this.configCollector.allAnswers = {}; this.configCollector.allAnswers = {};
for (const [key, value] of Object.entries(customConfig.coreConfig)) { for (const [key, value] of Object.entries(customConfig.coreConfig)) {
@ -883,7 +888,6 @@ class Installer {
} }
// Modules to collect configs for — skip core if its config was pre-collected from UI // Modules to collect configs for — skip core if its config was pre-collected from UI
const hasCoreConfig = customConfig.coreConfig && Object.keys(customConfig.coreConfig).length > 0;
const toCollect = hasCoreConfig ? (customConfig.modules || []).filter((m) => m !== 'core') : [...(customConfig.modules || [])]; const toCollect = hasCoreConfig ? (customConfig.modules || []).filter((m) => m !== 'core') : [...(customConfig.modules || [])];
return await this.configCollector.collectAllConfigurations(toCollect, paths.projectRoot, { return await this.configCollector.collectAllConfigurations(toCollect, paths.projectRoot, {