diff --git a/app/env_pro/commands/core.py b/app/env_pro/commands/core.py new file mode 100644 index 0000000..340337b --- /dev/null +++ b/app/env_pro/commands/core.py @@ -0,0 +1,133 @@ +"""Core CLI commands for env-pro.""" + +import click +from pathlib import Path +from typing import Optional + + +@click.command() +def init(): + """Initialize env-pro in the current directory.""" + from env_pro.core.profile import init_project + + profiles_dir = init_project() + click.echo(f"Initialized env-pro in {profiles_dir}") + click.echo("Created 'default' profile. Use 'env-pro profile create' to create more.") + + +@click.command() +@click.argument("key") +@click.argument("value", required=False) +@click.option("--encrypt/--no-encrypt", default=False, help="Encrypt the value") +@click.option("--interactive", "-i", is_flag=True, help="Prompt for value") +def add(key: str, value: Optional[str], encrypt: bool, interactive: bool): + """Add or update an environment variable.""" + from env_pro.core.profile import get_active_profile, get_profile_vars, set_profile_var + from env_pro.core.encryption import encrypt_value, generate_key, get_key_from_keyring + + profile = get_active_profile() or "default" + + if interactive and value is None: + value = click.prompt(f"Enter value for {key}", hide_input=encrypt) + + if value is None: + raise click.ClickException("Value is required (use argument or --interactive)") + + if encrypt: + keyring_key = get_key_from_keyring() + if keyring_key is None: + keyring_key = generate_key() + from env_pro.core.encryption import store_key_in_keyring + store_key_in_keyring(keyring_key) + click.echo("Generated new encryption key") + + value = encrypt_value(value, keyring_key) + click.echo(f"Encrypted value for {key}") + + set_profile_var(profile, key, value) + click.echo(f"Set {key} in profile '{profile}'") + + +@click.command() +@click.argument("key") +@click.argument("value") +@click.option("--encrypt/--no-encrypt", default=False, help="Encrypt the value") +def set(key: str, value: str, encrypt: bool): + """Set an environment variable (alias for add).""" + from env_pro.core.profile import get_active_profile, set_profile_var + from env_pro.core.encryption import encrypt_value, generate_key, get_key_from_keyring + + profile = get_active_profile() or "default" + + if encrypt: + keyring_key = get_key_from_keyring() + if keyring_key is None: + keyring_key = generate_key() + from env_pro.core.encryption import store_key_in_keyring + store_key_in_keyring(keyring_key) + click.echo("Generated new encryption key") + + value = encrypt_value(value, keyring_key) + click.echo(f"Encrypted value for {key}") + + set_profile_var(profile, key, value) + click.echo(f"Set {key} in profile '{profile}'") + + +@click.command() +@click.argument("key") +@click.option("--decrypt/--no-decrypt", default=False, help="Decrypt the value") +def get(key: str, decrypt: bool): + """Get an environment variable.""" + from env_pro.core.profile import get_active_profile, get_profile_vars + from env_pro.core.encryption import decrypt_value, get_key_from_keyring + + profile = get_active_profile() or "default" + vars = get_profile_vars(profile) + + if key not in vars: + raise click.ClickException(f"Key '{key}' not found in profile '{profile}'") + + value = vars[key] + + if decrypt: + keyring_key = get_key_from_keyring() + if keyring_key is None: + raise click.ClickException("No encryption key found. Run 'env-pro key generate' first.") + + try: + value = decrypt_value(value, keyring_key) + except Exception as e: + raise click.ClickException(f"Failed to decrypt: {e}") + + click.echo(value) + + +@click.command() +def list(): + """List all environment variables.""" + from env_pro.core.profile import get_active_profile, get_profile_vars + + profile = get_active_profile() or "default" + vars = get_profile_vars(profile) + + if not vars: + click.echo(f"No variables in profile '{profile}'") + return + + click.echo(f"Variables in profile '{profile}':") + for key, value in vars.items(): + if len(value) > 50: + value = value[:47] + "..." + click.echo(f" {key}={value}") + + +@click.command() +@click.argument("key") +def delete(key: str): + """Delete an environment variable.""" + from env_pro.core.profile import get_active_profile, delete_profile_var + + profile = get_active_profile() or "default" + delete_profile_var(profile, key) + click.echo(f"Deleted {key} from profile '{profile}'")