muapi-cli 0.2.5__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
muapi/commands/keys.py ADDED
@@ -0,0 +1,115 @@
1
+ """muapi keys — list, create, and delete API keys."""
2
+ import json
3
+
4
+ import httpx
5
+ import typer
6
+
7
+ from .. import exitcodes
8
+ from ..config import BASE_URL, get_api_key
9
+ from ..utils import console, error_exit, out
10
+
11
+ app = typer.Typer(help="Manage API keys for your muapi.ai account.")
12
+
13
+
14
+ def _headers() -> dict:
15
+ key = get_api_key()
16
+ if not key:
17
+ error_exit("No API key configured. Run: muapi auth configure", exitcodes.AUTH_ERROR)
18
+ return {"x-api-key": key}
19
+
20
+
21
+ @app.command("list")
22
+ def list_keys(
23
+ output_json: bool = typer.Option(False, "--output-json", "-j", help="Print raw JSON"),
24
+ ):
25
+ """List all API keys on your account."""
26
+ try:
27
+ resp = httpx.get(f"{BASE_URL}/keys", headers=_headers(), timeout=30.0)
28
+ except httpx.RequestError as exc:
29
+ error_exit(f"Network error: {exc}", exitcodes.ERROR)
30
+
31
+ if resp.status_code in (401, 403):
32
+ error_exit("Authentication failed. Run: muapi auth configure", exitcodes.AUTH_ERROR)
33
+ if resp.status_code >= 400:
34
+ error_exit(f"Request failed: {resp.text}", exitcodes.ERROR)
35
+
36
+ keys = resp.json()
37
+ if output_json:
38
+ out.print_json(json.dumps(keys))
39
+ return
40
+
41
+ if not keys:
42
+ console.print("No API keys found.")
43
+ return
44
+
45
+ from rich.table import Table
46
+ table = Table(show_header=True, header_style="bold")
47
+ table.add_column("ID", style="dim")
48
+ table.add_column("Name")
49
+ table.add_column("Active")
50
+ table.add_column("Created")
51
+ table.add_column("Last Used")
52
+ for k in keys:
53
+ table.add_row(
54
+ str(k["id"]),
55
+ k["name"],
56
+ "[green]yes[/green]" if k["is_active"] else "[red]no[/red]",
57
+ (k.get("created_at") or "")[:10],
58
+ (k.get("last_used_at") or "never")[:10],
59
+ )
60
+ console.print(table)
61
+
62
+
63
+ @app.command("create")
64
+ def create_key(
65
+ name: str = typer.Option("cli", "--name", "-n", help="Label for this key"),
66
+ output_json: bool = typer.Option(False, "--output-json", "-j", help="Print raw JSON"),
67
+ ):
68
+ """Create a new API key (shown once — save it immediately)."""
69
+ try:
70
+ resp = httpx.post(
71
+ f"{BASE_URL}/keys",
72
+ json={"name": name},
73
+ headers=_headers(),
74
+ timeout=30.0,
75
+ )
76
+ except httpx.RequestError as exc:
77
+ error_exit(f"Network error: {exc}", exitcodes.ERROR)
78
+
79
+ if resp.status_code in (401, 403):
80
+ error_exit("Authentication failed. Run: muapi auth configure", exitcodes.AUTH_ERROR)
81
+ if resp.status_code >= 400:
82
+ error_exit(f"Request failed: {resp.text}", exitcodes.ERROR)
83
+
84
+ data = resp.json()
85
+ if output_json:
86
+ out.print_json(json.dumps(data))
87
+ return
88
+
89
+ console.print(f"[bold green]API key created (ID {data['id']}):[/bold green]")
90
+ console.print(f"[bold yellow]{data['api_key']}[/bold yellow]")
91
+ console.print("[dim]Save it now — it won't be shown again.[/dim]")
92
+
93
+
94
+ @app.command("delete")
95
+ def delete_key(
96
+ key_id: int = typer.Argument(..., help="ID of the key to delete (from 'muapi keys list')"),
97
+ yes: bool = typer.Option(False, "--yes", "-y", help="Skip confirmation prompt"),
98
+ ):
99
+ """Delete an API key by ID."""
100
+ if not yes:
101
+ typer.confirm(f"Delete API key ID {key_id}?", abort=True)
102
+
103
+ try:
104
+ resp = httpx.delete(f"{BASE_URL}/keys/{key_id}", headers=_headers(), timeout=30.0)
105
+ except httpx.RequestError as exc:
106
+ error_exit(f"Network error: {exc}", exitcodes.ERROR)
107
+
108
+ if resp.status_code == 404:
109
+ error_exit(f"API key {key_id} not found.", exitcodes.NOT_FOUND)
110
+ if resp.status_code in (401, 403):
111
+ error_exit("Authentication failed.", exitcodes.AUTH_ERROR)
112
+ if resp.status_code >= 400:
113
+ error_exit(f"Request failed: {resp.text}", exitcodes.ERROR)
114
+
115
+ console.print(f"[green]API key {key_id} deleted.[/green]")