seizu-cli 2.0.0__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.
@@ -0,0 +1,223 @@
1
+ """CLI commands for managing reports."""
2
+
3
+ import json
4
+ import sys
5
+ from typing import Any
6
+
7
+ import typer
8
+ from rich.console import Console
9
+ from rich.table import Table
10
+
11
+ from seizu_cli import state
12
+ from seizu_cli.client import APIError
13
+
14
+ app = typer.Typer(help="Manage reports.", no_args_is_help=True)
15
+ console = Console()
16
+ err_console = Console(stderr=True)
17
+
18
+
19
+ def _die(exc: Exception) -> None:
20
+ if isinstance(exc, APIError):
21
+ err_console.print(f"[red]Error {exc.status_code}[/red]: {exc}")
22
+ else:
23
+ err_console.print(f"[red]Error[/red]: {exc}")
24
+ sys.exit(1)
25
+
26
+
27
+ def _print_report_detail(data: dict[str, Any], as_json: bool) -> None:
28
+ if as_json:
29
+ sanitized = dict(data)
30
+ sanitized.pop("query_capabilities", None)
31
+ console.print_json(json.dumps(sanitized))
32
+ return
33
+ console.print(f"[bold]ID[/bold]: {data['report_id']}")
34
+ console.print(f"[bold]Name[/bold]: {data['name']}")
35
+ console.print(f"[bold]Version[/bold]: {data['version']}")
36
+ console.print(f"[bold]Access[/bold]: {data.get('access', {}).get('scope', 'unknown')}")
37
+ console.print(f"[bold]Created By[/bold]: {data['created_by']}")
38
+ console.print(f"[bold]Created At[/bold]: {data['created_at']}")
39
+ if data.get("comment"):
40
+ console.print(f"[bold]Comment[/bold]: {data['comment']}")
41
+
42
+
43
+ @app.command("list")
44
+ def list_reports(
45
+ output: str = typer.Option("table", "--output", "-o", help="Output format: table or json."),
46
+ ) -> None:
47
+ """List all reports."""
48
+ try:
49
+ data = state.get_client().get("/api/v1/reports")
50
+ except Exception as exc:
51
+ _die(exc)
52
+ return
53
+
54
+ if output == "json":
55
+ console.print_json(json.dumps(data))
56
+ return
57
+
58
+ reports = data.get("reports", [])
59
+ if not reports:
60
+ console.print("[dim]No reports found.[/dim]")
61
+ return
62
+
63
+ table = Table(show_header=True, header_style="bold")
64
+ table.add_column("ID")
65
+ table.add_column("Name")
66
+ table.add_column("Access")
67
+ table.add_column("Version", justify="right")
68
+ table.add_column("Updated At")
69
+
70
+ for r in reports:
71
+ table.add_row(
72
+ r["report_id"],
73
+ r["name"],
74
+ r.get("access", {}).get("scope", "unknown"),
75
+ str(r["current_version"]),
76
+ r["updated_at"],
77
+ )
78
+
79
+ console.print(table)
80
+
81
+
82
+ @app.command("get")
83
+ def get_report(
84
+ report_id: str = typer.Argument(help="Report ID."),
85
+ output: str = typer.Option("table", "--output", "-o", help="Output format: table or json."),
86
+ ) -> None:
87
+ """Get the latest version of a report."""
88
+ try:
89
+ data = state.get_client().get(f"/api/v1/reports/{report_id}")
90
+ except Exception as exc:
91
+ _die(exc)
92
+ return
93
+ _print_report_detail(data, as_json=(output == "json"))
94
+
95
+
96
+ @app.command("create")
97
+ def create_report(
98
+ name: str = typer.Argument(help="Report name."),
99
+ ) -> None:
100
+ """Create a new empty report."""
101
+ try:
102
+ data = state.get_client().post("/api/v1/reports", json={"name": name})
103
+ except Exception as exc:
104
+ _die(exc)
105
+ return
106
+ console.print(f"[green]Created[/green]: {data['report_id']} name={data['name']!r}")
107
+
108
+
109
+ @app.command("clone")
110
+ def clone_report(
111
+ report_id: str = typer.Argument(help="Source report ID."),
112
+ name: str = typer.Argument(help="Name for the cloned report."),
113
+ ) -> None:
114
+ """Clone a report into a new report."""
115
+ try:
116
+ data = state.get_client().post(f"/api/v1/reports/{report_id}/clone", json={"name": name})
117
+ except Exception as exc:
118
+ _die(exc)
119
+ return
120
+ console.print(f"[green]Cloned[/green]: {data['report_id']} name={data['name']!r} source={report_id!r}")
121
+
122
+
123
+ @app.command("publish")
124
+ def publish_report(
125
+ report_id: str = typer.Argument(help="Report ID."),
126
+ ) -> None:
127
+ """Make a report public."""
128
+ try:
129
+ state.get_client().put(f"/api/v1/reports/{report_id}/visibility", json={"access": {"scope": "public"}})
130
+ except Exception as exc:
131
+ _die(exc)
132
+ return
133
+ console.print(f"[green]Published[/green]: {report_id}")
134
+
135
+
136
+ @app.command("unpublish")
137
+ def unpublish_report(
138
+ report_id: str = typer.Argument(help="Report ID."),
139
+ ) -> None:
140
+ """Make a report private."""
141
+ try:
142
+ state.get_client().put(f"/api/v1/reports/{report_id}/visibility", json={"access": {"scope": "private"}})
143
+ except Exception as exc:
144
+ _die(exc)
145
+ return
146
+ console.print(f"[green]Unpublished[/green]: {report_id}")
147
+
148
+
149
+ @app.command("delete")
150
+ def delete_report(
151
+ report_id: str = typer.Argument(help="Report ID."),
152
+ yes: bool = typer.Option(False, "--yes", "-y", help="Skip confirmation prompt."),
153
+ ) -> None:
154
+ """Delete a report and all its versions."""
155
+ if not yes:
156
+ typer.confirm(f"Delete report {report_id!r} and all its versions?", abort=True)
157
+ try:
158
+ state.get_client().delete(f"/api/v1/reports/{report_id}")
159
+ except Exception as exc:
160
+ _die(exc)
161
+ return
162
+ console.print(f"[red]Deleted[/red]: {report_id}")
163
+
164
+
165
+ @app.command("set-dashboard")
166
+ def set_dashboard(
167
+ report_id: str = typer.Argument(help="Report ID to set as the default dashboard."),
168
+ ) -> None:
169
+ """Set a report as the default dashboard."""
170
+ try:
171
+ state.get_client().put(f"/api/v1/reports/{report_id}/dashboard")
172
+ except Exception as exc:
173
+ _die(exc)
174
+ return
175
+ console.print(f"[green]Dashboard set to[/green]: {report_id}")
176
+
177
+
178
+ @app.command("versions")
179
+ def list_versions(
180
+ report_id: str = typer.Argument(help="Report ID."),
181
+ output: str = typer.Option("table", "--output", "-o", help="Output format: table or json."),
182
+ ) -> None:
183
+ """List all versions of a report."""
184
+ try:
185
+ data = state.get_client().get(f"/api/v1/reports/{report_id}/versions")
186
+ except Exception as exc:
187
+ _die(exc)
188
+ return
189
+
190
+ if output == "json":
191
+ console.print_json(json.dumps(data))
192
+ return
193
+
194
+ versions = data.get("versions", [])
195
+ table = Table(show_header=True, header_style="bold")
196
+ table.add_column("Version", justify="right")
197
+ table.add_column("Created By")
198
+ table.add_column("Created At")
199
+ table.add_column("Comment")
200
+
201
+ for v in versions:
202
+ table.add_row(
203
+ str(v["version"]),
204
+ v["created_by"],
205
+ v["created_at"],
206
+ v.get("comment") or "",
207
+ )
208
+ console.print(table)
209
+
210
+
211
+ @app.command("version-get")
212
+ def get_version(
213
+ report_id: str = typer.Argument(help="Report ID."),
214
+ version: int = typer.Argument(help="Version number."),
215
+ output: str = typer.Option("table", "--output", "-o", help="Output format: table or json."),
216
+ ) -> None:
217
+ """Get a specific version of a report."""
218
+ try:
219
+ data = state.get_client().get(f"/api/v1/reports/{report_id}/versions/{version}")
220
+ except Exception as exc:
221
+ _die(exc)
222
+ return
223
+ _print_report_detail(data, as_json=(output == "json"))
@@ -0,0 +1,157 @@
1
+ """CLI commands for managing scheduled queries."""
2
+
3
+ import json
4
+ import sys
5
+ from typing import Any
6
+
7
+ import typer
8
+ from rich.console import Console
9
+ from rich.table import Table
10
+
11
+ from seizu_cli import state
12
+ from seizu_cli.client import APIError
13
+
14
+ app = typer.Typer(help="Manage scheduled queries.", no_args_is_help=True)
15
+ console = Console()
16
+ err_console = Console(stderr=True)
17
+
18
+
19
+ def _die(exc: Exception) -> None:
20
+ if isinstance(exc, APIError):
21
+ err_console.print(f"[red]Error {exc.status_code}[/red]: {exc}")
22
+ else:
23
+ err_console.print(f"[red]Error[/red]: {exc}")
24
+ sys.exit(1)
25
+
26
+
27
+ def _print_sq_detail(data: dict[str, Any], as_json: bool) -> None:
28
+ if as_json:
29
+ console.print_json(json.dumps(data))
30
+ return
31
+ console.print(f"[bold]ID[/bold]: {data['scheduled_query_id']}")
32
+ console.print(f"[bold]Name[/bold]: {data['name']}")
33
+ console.print(f"[bold]Enabled[/bold]: {data.get('enabled', True)}")
34
+ console.print(f"[bold]Frequency[/bold]: {data.get('frequency')}")
35
+ console.print(f"[bold]Version[/bold]: {data.get('current_version', data.get('version'))}")
36
+ console.print(f"[bold]Created By[/bold]: {data['created_by']}")
37
+ console.print(f"[bold]Updated By[/bold]: {data.get('updated_by', '')}")
38
+ console.print(f"[bold]Cypher[/bold]\n{data['cypher']}")
39
+
40
+
41
+ @app.command("list")
42
+ def list_scheduled_queries(
43
+ output: str = typer.Option("table", "--output", "-o", help="Output format: table or json."),
44
+ ) -> None:
45
+ """List all scheduled queries."""
46
+ try:
47
+ data = state.get_client().get("/api/v1/scheduled-queries")
48
+ except Exception as exc:
49
+ _die(exc)
50
+ return
51
+
52
+ if output == "json":
53
+ console.print_json(json.dumps(data))
54
+ return
55
+
56
+ items = data.get("scheduled_queries", [])
57
+ if not items:
58
+ console.print("[dim]No scheduled queries found.[/dim]")
59
+ return
60
+
61
+ table = Table(show_header=True, header_style="bold")
62
+ table.add_column("ID")
63
+ table.add_column("Name")
64
+ table.add_column("Enabled")
65
+ table.add_column("Frequency (s)", justify="right")
66
+ table.add_column("Version", justify="right")
67
+ table.add_column("Updated At")
68
+
69
+ for q in items:
70
+ table.add_row(
71
+ q["scheduled_query_id"],
72
+ q["name"],
73
+ "yes" if q.get("enabled", True) else "no",
74
+ str(q.get("frequency") or ""),
75
+ str(q.get("current_version", "")),
76
+ q.get("updated_at", ""),
77
+ )
78
+
79
+ console.print(table)
80
+
81
+
82
+ @app.command("get")
83
+ def get_scheduled_query(
84
+ sq_id: str = typer.Argument(help="Scheduled query ID."),
85
+ output: str = typer.Option("table", "--output", "-o", help="Output format: table or json."),
86
+ ) -> None:
87
+ """Get a scheduled query by ID."""
88
+ try:
89
+ data = state.get_client().get(f"/api/v1/scheduled-queries/{sq_id}")
90
+ except Exception as exc:
91
+ _die(exc)
92
+ return
93
+ _print_sq_detail(data, as_json=(output == "json"))
94
+
95
+
96
+ @app.command("delete")
97
+ def delete_scheduled_query(
98
+ sq_id: str = typer.Argument(help="Scheduled query ID."),
99
+ yes: bool = typer.Option(False, "--yes", "-y", help="Skip confirmation prompt."),
100
+ ) -> None:
101
+ """Delete a scheduled query."""
102
+ if not yes:
103
+ typer.confirm(f"Delete scheduled query {sq_id!r}?", abort=True)
104
+ try:
105
+ state.get_client().delete(f"/api/v1/scheduled-queries/{sq_id}")
106
+ except Exception as exc:
107
+ _die(exc)
108
+ return
109
+ console.print(f"[red]Deleted[/red]: {sq_id}")
110
+
111
+
112
+ @app.command("versions")
113
+ def list_versions(
114
+ sq_id: str = typer.Argument(help="Scheduled query ID."),
115
+ output: str = typer.Option("table", "--output", "-o", help="Output format: table or json."),
116
+ ) -> None:
117
+ """List all versions of a scheduled query."""
118
+ try:
119
+ data = state.get_client().get(f"/api/v1/scheduled-queries/{sq_id}/versions")
120
+ except Exception as exc:
121
+ _die(exc)
122
+ return
123
+
124
+ if output == "json":
125
+ console.print_json(json.dumps(data))
126
+ return
127
+
128
+ versions = data.get("versions", [])
129
+ table = Table(show_header=True, header_style="bold")
130
+ table.add_column("Version", justify="right")
131
+ table.add_column("Created By")
132
+ table.add_column("Created At")
133
+ table.add_column("Comment")
134
+
135
+ for v in versions:
136
+ table.add_row(
137
+ str(v["version"]),
138
+ v["created_by"],
139
+ v["created_at"],
140
+ v.get("comment") or "",
141
+ )
142
+ console.print(table)
143
+
144
+
145
+ @app.command("version-get")
146
+ def get_version(
147
+ sq_id: str = typer.Argument(help="Scheduled query ID."),
148
+ version: int = typer.Argument(help="Version number."),
149
+ output: str = typer.Option("table", "--output", "-o", help="Output format: table or json."),
150
+ ) -> None:
151
+ """Get a specific version of a scheduled query."""
152
+ try:
153
+ data = state.get_client().get(f"/api/v1/scheduled-queries/{sq_id}/versions/{version}")
154
+ except Exception as exc:
155
+ _die(exc)
156
+ return
157
+ _print_sq_detail(data, as_json=(output == "json"))