summaryrefslogtreecommitdiff
path: root/packages/cli/src/config
diff options
context:
space:
mode:
Diffstat (limited to 'packages/cli/src/config')
-rw-r--r--packages/cli/src/config/args.ts43
-rw-r--r--packages/cli/src/config/config.ts110
-rw-r--r--packages/cli/src/config/env.ts48
-rw-r--r--packages/cli/src/config/globalConfig.ts50
4 files changed, 110 insertions, 141 deletions
diff --git a/packages/cli/src/config/args.ts b/packages/cli/src/config/args.ts
deleted file mode 100644
index a71b4b66..00000000
--- a/packages/cli/src/config/args.ts
+++ /dev/null
@@ -1,43 +0,0 @@
-import yargs from 'yargs/yargs';
-import { hideBin } from 'yargs/helpers';
-
-const DEFAULT_GEMINI_MODEL = 'gemini-2.5-flash-preview-04-17';
-
-export interface CliArgs {
- target_dir: string | undefined;
- model: string | undefined;
- _: Array<string | number>; // Captures positional arguments
- // Add other expected args here if needed
- // e.g., verbose?: boolean;
-}
-
-export async function parseArguments(): Promise<CliArgs> {
- const argv = await 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
- .parseAsync();
-
- // Handle warnings for extra arguments here
- if (argv._ && argv._.length > 0) {
- console.warn(
- `Warning: Additional arguments provided (${argv._.join(', ')}), but will be ignored.`,
- );
- }
-
- // 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;
-}
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 });
+}
diff --git a/packages/cli/src/config/env.ts b/packages/cli/src/config/env.ts
deleted file mode 100644
index 51fc0a9c..00000000
--- a/packages/cli/src/config/env.ts
+++ /dev/null
@@ -1,48 +0,0 @@
-import * as dotenv from 'dotenv';
-import * as fs from 'node:fs';
-import * as path from 'node:path';
-import process from 'node:process';
-
-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;
- }
-}
-
-export function loadEnvironment(): void {
- // Start searching from the current working directory by default
- const envFilePath = findEnvFile(process.cwd());
-
- if (envFilePath) {
- dotenv.config({ path: envFilePath });
- }
-
- if (!process.env.GEMINI_API_KEY?.length) {
- console.error(
- 'Error: GEMINI_API_KEY environment variable is not set. Please visit https://ai.google.dev/gemini-api/docs/api-key to set up a new one.',
- );
- process.exit(0);
- }
-}
-
-export function getApiKey(): string {
- loadEnvironment();
- const apiKey = process.env.GEMINI_API_KEY;
- if (!apiKey) {
- throw new Error(
- 'GEMINI_API_KEY environment variable is not set. Please visit https://ai.google.dev/gemini-api/docs/api-key to set up a new one.',
- );
- }
- return apiKey;
-}
diff --git a/packages/cli/src/config/globalConfig.ts b/packages/cli/src/config/globalConfig.ts
deleted file mode 100644
index 2b6ad518..00000000
--- a/packages/cli/src/config/globalConfig.ts
+++ /dev/null
@@ -1,50 +0,0 @@
-import { CliArgs } from './args.js'; // Assuming CliArgs contains the needed fields
-
-interface GlobalConfig {
- model: string;
- // Add other global config values here if needed
- // e.g., targetDir?: string;
-}
-
-let config: GlobalConfig | null = null;
-
-/**
- * Initializes the global configuration. Should only be called once at application startup.
- * @param args The parsed command-line arguments.
- */
-export function initializeConfig(args: Pick<CliArgs, 'model'>): void {
- if (config) {
- console.warn('Global configuration already initialized.');
- return;
- }
- if (!args.model) {
- // This shouldn't happen if default is set correctly in args.ts
- throw new Error('Model not provided during config initialization.');
- }
- config = {
- model: args.model,
- // Initialize other config values from args here
- };
-}
-
-/**
- * Retrieves the globally stored configuration.
- * Throws an error if the configuration has not been initialized.
- * @returns The global configuration object.
- */
-export function getConfig(): GlobalConfig {
- if (!config) {
- throw new Error(
- 'Global configuration accessed before initialization. Call initializeConfig() first.',
- );
- }
- return config;
-}
-
-/**
- * Helper function to get the configured Gemini model name.
- * @returns The model name string.
- */
-export function getModel(): string {
- return getConfig().model;
-} \ No newline at end of file