Skip to content

Commit cc17315

Browse files
committed
feat: replace cosmiconfig with c12 for configuration management
- Replace cosmiconfig with c12 for better TypeScript support - Add configuration watching capability - Remove dependency on cosmiconfig - Maintain backward compatibility with existing config files - Closes #260
1 parent 72f9801 commit cc17315

File tree

2 files changed

+41
-26
lines changed

2 files changed

+41
-26
lines changed

packages/cli/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,8 @@
4646
"license": "MIT",
4747
"dependencies": {
4848
"@sentry/node": "^9.3.0",
49+
"c12": "^3.0.2",
4950
"chalk": "^5",
50-
"cosmiconfig": "^9.0.0",
5151
"deepmerge": "^4.3.1",
5252
"dotenv": "^16",
5353
"mycoder-agent": "workspace:*",

packages/cli/src/settings/config.ts

+40-25
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { cosmiconfig } from 'cosmiconfig';
1+
import { loadConfig as loadC12Config, watchConfig } from 'c12';
22
import { ArgumentsCamelCase } from 'yargs';
33

44
import { SharedOptions } from '../options';
@@ -107,12 +107,6 @@ export const getConfigFromArgv = (argv: ArgumentsCamelCase<SharedOptions>) => {
107107
};
108108
};
109109

110-
function removeUndefined(obj: any) {
111-
return Object.fromEntries(
112-
Object.entries(obj).filter(([_, value]) => value !== undefined),
113-
);
114-
}
115-
116110
/**
117111
* Validates custom commands configuration
118112
* @param config The configuration object
@@ -138,32 +132,53 @@ function validateCustomCommands(config: Config): void {
138132
});
139133
}
140134
/**
141-
* Load configuration using cosmiconfig
135+
* Load configuration using c12
142136
* @returns Merged configuration with default values
143137
*/
144138
export async function loadConfig(
145139
cliOptions: Partial<Config> = {},
146140
): Promise<Config> {
147-
// Initialize cosmiconfig
148-
const explorer = cosmiconfig('mycoder', {
149-
searchStrategy: 'global',
141+
// Load configuration using c12
142+
const { config } = await loadC12Config({
143+
name: 'mycoder',
144+
defaults: defaultConfig,
145+
overrides: cliOptions,
146+
// Optionally enable .env support
147+
// dotenv: true,
150148
});
151149

152-
// Search for configuration file
153-
const result = await explorer.search();
154-
155-
// Merge configurations with precedence: default < file < cli
156-
const fileConfig = result?.config || {};
150+
// Convert to Config type and validate custom commands
151+
const typedConfig = config as unknown as Config;
152+
validateCustomCommands(typedConfig);
157153

158-
// Return merged configuration
159-
const mergedConfig = {
160-
...defaultConfig,
161-
...removeUndefined(fileConfig),
162-
...removeUndefined(cliOptions),
163-
};
154+
return typedConfig;
155+
}
164156

165-
// Validate custom commands if present
166-
validateCustomCommands(mergedConfig);
157+
/**
158+
* Watch configuration for changes
159+
* @param cliOptions CLI options to override configuration
160+
* @param onUpdate Callback when configuration is updated
161+
*/
162+
export async function watchConfigForChanges(
163+
cliOptions: Partial<Config> = {},
164+
onUpdate?: (config: Config) => void,
165+
) {
166+
const { config, watchingFiles, unwatch } = await watchConfig({
167+
name: 'mycoder',
168+
defaults: defaultConfig,
169+
overrides: cliOptions,
170+
onUpdate: ({ newConfig }) => {
171+
const typedConfig = newConfig as unknown as Config;
172+
validateCustomCommands(typedConfig);
173+
if (onUpdate) {
174+
onUpdate(typedConfig);
175+
}
176+
},
177+
});
167178

168-
return mergedConfig;
179+
return {
180+
config: config as unknown as Config,
181+
watchingFiles,
182+
unwatch,
183+
};
169184
}

0 commit comments

Comments
 (0)