summaryrefslogtreecommitdiff
path: root/packages/cli/src/config/config.ts
diff options
context:
space:
mode:
authorJaana Dogan <[email protected]>2025-04-18 11:12:18 -0700
committerGitHub <[email protected]>2025-04-18 11:12:18 -0700
commit3afaa8033bdd9d6af99ff378cafcd84afd76c59e (patch)
treeeecba3f035a7147281dfe4db5ca015108ae9d3dc /packages/cli/src/config/config.ts
parente1fac4025606246e284b3e370d22100e8a25d652 (diff)
Introduce a config module to manage configuration (#22)
* Introduce a config module to manage configuration * Remove public modifier
Diffstat (limited to 'packages/cli/src/config/config.ts')
-rw-r--r--packages/cli/src/config/config.ts110
1 files changed, 110 insertions, 0 deletions
diff --git a/packages/cli/src/config/config.ts b/packages/cli/src/config/config.ts
new file mode 100644
index 00000000..ca9cbc18
--- /dev/null
+++ b/packages/cli/src/config/config.ts
@@ -0,0 +1,110 @@
+import yargs from 'yargs/yargs';
+import { hideBin } from 'yargs/helpers';
+import * as dotenv from 'dotenv';
+import * as fs from 'node:fs';
+import * as path from 'node:path';
+import process from 'node:process';
+
+const DEFAULT_GEMINI_MODEL = 'gemini-2.5-flash-preview-04-17';
+
+export class Config {
+ private apiKey: string;
+ private model: string;
+ private targetDir: string;
+ private extraArgs: (string | number)[]; // Captures positional arguments
+
+ constructor(apiKey: string, model: string, targetDir: string, extraArgs: (string | number)[]) {
+ this.apiKey = apiKey;
+ this.model = model;
+ this.targetDir = targetDir;
+ this.extraArgs = extraArgs;
+ }
+
+ getApiKey(): string {
+ return this.apiKey;
+ }
+
+ getModel(): string {
+ return this.model;
+ }
+
+ getTargetDir(): string {
+ return this.targetDir;
+ }
+
+ getExtraArgs(): (string | number)[] {
+ return this.extraArgs;
+ }
+}
+
+export function loadConfig(): Config {
+ loadEnvironment();
+ const argv = parseArguments();
+ return new Config(
+ process.env.GEMINI_API_KEY || "",
+ argv.model || process.env.GEMINI_API_KEY || DEFAULT_GEMINI_MODEL,
+ argv.target_dir || process.cwd(),
+ argv._,
+ );
+}
+
+export const globalConfig = loadConfig(); // TODO(jbd): Remove global state.
+
+interface CliArgs {
+ target_dir: string | undefined;
+ model: string | undefined;
+ _: (string | number)[]; // Captures positional arguments
+ // Add other expected args here if needed
+ // e.g., verbose?: boolean;
+}
+
+function parseArguments(): CliArgs {
+ const argv = yargs(hideBin(process.argv))
+ .option('target_dir', {
+ alias: 'd',
+ type: 'string',
+ description:
+ 'The target directory for Gemini operations. Defaults to the current working directory.',
+ })
+ .option('model', {
+ alias: 'm',
+ type: 'string',
+ description: `The Gemini model to use. Defaults to ${DEFAULT_GEMINI_MODEL}.`,
+ default: DEFAULT_GEMINI_MODEL,
+ })
+ .help()
+ .alias('h', 'help')
+ .strict() // Keep strict mode to error on unknown options
+ .argv;
+
+ // Cast to the interface to ensure the structure aligns with expectations
+ // Use `unknown` first for safer casting if types might not perfectly match
+ return argv as unknown as CliArgs;
+}
+
+
+function findEnvFile(startDir: string): string | null {
+ // Start search from the provided directory (e.g., current working directory)
+ let currentDir = path.resolve(startDir); // Ensure absolute path
+ while (true) {
+ const envPath = path.join(currentDir, '.env');
+ if (fs.existsSync(envPath)) {
+ return envPath;
+ }
+
+ const parentDir = path.dirname(currentDir);
+ if (parentDir === currentDir || !parentDir) {
+ return null;
+ }
+ currentDir = parentDir;
+ }
+}
+
+function loadEnvironment(): void {
+ // Start searching from the current working directory by default
+ const envFilePath = findEnvFile(process.cwd());
+ if (!envFilePath) {
+ return;
+ }
+ dotenv.config({ path: envFilePath });
+}