kctl-vendure 0.6.2__tar.gz
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.
- kctl_vendure-0.6.2/.gitignore +33 -0
- kctl_vendure-0.6.2/PKG-INFO +17 -0
- kctl_vendure-0.6.2/README.md +120 -0
- kctl_vendure-0.6.2/pyproject.toml +43 -0
- kctl_vendure-0.6.2/skills/vendure-admin/SKILL.md +78 -0
- kctl_vendure-0.6.2/src/kctl_vendure/__init__.py +3 -0
- kctl_vendure-0.6.2/src/kctl_vendure/__main__.py +5 -0
- kctl_vendure-0.6.2/src/kctl_vendure/cli.py +101 -0
- kctl_vendure-0.6.2/src/kctl_vendure/commands/__init__.py +0 -0
- kctl_vendure-0.6.2/src/kctl_vendure/commands/assets.py +90 -0
- kctl_vendure-0.6.2/src/kctl_vendure/commands/config_cmd.py +108 -0
- kctl_vendure-0.6.2/src/kctl_vendure/commands/customers.py +104 -0
- kctl_vendure-0.6.2/src/kctl_vendure/commands/doctor.py +83 -0
- kctl_vendure-0.6.2/src/kctl_vendure/commands/orders.py +247 -0
- kctl_vendure-0.6.2/src/kctl_vendure/commands/payments.py +98 -0
- kctl_vendure-0.6.2/src/kctl_vendure/commands/products.py +133 -0
- kctl_vendure-0.6.2/src/kctl_vendure/core/__init__.py +0 -0
- kctl_vendure-0.6.2/src/kctl_vendure/core/callbacks.py +41 -0
- kctl_vendure-0.6.2/src/kctl_vendure/core/client.py +177 -0
- kctl_vendure-0.6.2/src/kctl_vendure/core/config.py +137 -0
- kctl_vendure-0.6.2/tests/__init__.py +0 -0
- kctl_vendure-0.6.2/tests/conftest.py +98 -0
- kctl_vendure-0.6.2/tests/test_cli.py +30 -0
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*.egg-info/
|
|
5
|
+
*.egg
|
|
6
|
+
dist/
|
|
7
|
+
build/
|
|
8
|
+
.eggs/
|
|
9
|
+
|
|
10
|
+
# Virtual environments
|
|
11
|
+
.venv/
|
|
12
|
+
venv/
|
|
13
|
+
|
|
14
|
+
# IDE
|
|
15
|
+
.idea/
|
|
16
|
+
.vscode/
|
|
17
|
+
*.swp
|
|
18
|
+
*.swo
|
|
19
|
+
|
|
20
|
+
# Testing
|
|
21
|
+
.pytest_cache/
|
|
22
|
+
.coverage
|
|
23
|
+
htmlcov/
|
|
24
|
+
.mypy_cache/
|
|
25
|
+
.ruff_cache/
|
|
26
|
+
|
|
27
|
+
# OS
|
|
28
|
+
.DS_Store
|
|
29
|
+
Thumbs.db
|
|
30
|
+
|
|
31
|
+
# Environment
|
|
32
|
+
.env
|
|
33
|
+
.env.local
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: kctl-vendure
|
|
3
|
+
Version: 0.6.2
|
|
4
|
+
Summary: Kodemeio Vendure CLI — manage Vendure e-commerce via GraphQL Admin API
|
|
5
|
+
Requires-Python: >=3.12
|
|
6
|
+
Requires-Dist: httpx>=0.28.0
|
|
7
|
+
Requires-Dist: kctl-lib>=0.7.0
|
|
8
|
+
Requires-Dist: pydantic>=2.10.0
|
|
9
|
+
Requires-Dist: pyyaml>=6.0.2
|
|
10
|
+
Requires-Dist: rich>=13.9.0
|
|
11
|
+
Requires-Dist: typer>=0.15.0
|
|
12
|
+
Provides-Extra: dev
|
|
13
|
+
Requires-Dist: mypy>=1.14.0; extra == 'dev'
|
|
14
|
+
Requires-Dist: pytest-httpx>=0.35.0; extra == 'dev'
|
|
15
|
+
Requires-Dist: pytest>=8.3.0; extra == 'dev'
|
|
16
|
+
Requires-Dist: ruff>=0.9.0; extra == 'dev'
|
|
17
|
+
Requires-Dist: types-pyyaml>=6.0.0; extra == 'dev'
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# kctl-vendure
|
|
2
|
+
|
|
3
|
+
Kodemeio Vendure CLI — manage e-commerce via GraphQL Admin API.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
# From workspace (development)
|
|
9
|
+
uv tool install --editable packages/kctl-vendure
|
|
10
|
+
|
|
11
|
+
# From PyPI
|
|
12
|
+
uv tool install kctl-vendure
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Quick Start
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
# Initialize configuration
|
|
19
|
+
kctl-vendure config init
|
|
20
|
+
|
|
21
|
+
# Test API connectivity
|
|
22
|
+
kctl-vendure config test
|
|
23
|
+
|
|
24
|
+
# List products
|
|
25
|
+
kctl-vendure products list
|
|
26
|
+
|
|
27
|
+
# List recent orders
|
|
28
|
+
kctl-vendure orders list --take 20
|
|
29
|
+
|
|
30
|
+
# View customer details
|
|
31
|
+
kctl-vendure customers show cust-123
|
|
32
|
+
|
|
33
|
+
# Check payment status
|
|
34
|
+
kctl-vendure payments list --order 456
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Command Groups
|
|
38
|
+
|
|
39
|
+
| Group | Commands | Description |
|
|
40
|
+
|-------|----------|-------------|
|
|
41
|
+
| `config` | init, add, use, show, set, remove, profiles, current, test, migrate | Manage profiles and credentials |
|
|
42
|
+
| `products` | list, show, create, update, delete, variants | Product catalog management |
|
|
43
|
+
| `orders` | list, show, update, cancel, refund, fulfill | Order lifecycle management |
|
|
44
|
+
| `customers` | list, show, create, update, delete | Customer account management |
|
|
45
|
+
| `assets` | list, show, upload, delete | Digital asset management |
|
|
46
|
+
| `payments` | list, show, settle, cancel | Payment processing operations |
|
|
47
|
+
| `doctor` | check | Diagnostic checks (GraphQL connectivity, auth, config) |
|
|
48
|
+
|
|
49
|
+
## Global Options
|
|
50
|
+
|
|
51
|
+
All commands accept these options:
|
|
52
|
+
|
|
53
|
+
| Option | Short | Description |
|
|
54
|
+
|--------|-------|-------------|
|
|
55
|
+
| `--json` | | Output as JSON |
|
|
56
|
+
| `--format` | `-f` | Output format: `pretty`, `json`, `csv`, `yaml` |
|
|
57
|
+
| `--quiet` | `-q` | Suppress info messages |
|
|
58
|
+
| `--no-header` | | Omit header row in table/CSV output |
|
|
59
|
+
| `--profile` | `-p` | Config profile name |
|
|
60
|
+
| `--version` | `-V` | Show version and exit |
|
|
61
|
+
|
|
62
|
+
## Configuration
|
|
63
|
+
|
|
64
|
+
Config is stored in `~/.config/kodemeio/config.yaml` under the `vendure` key.
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
# Create a new profile
|
|
68
|
+
kctl-vendure config init
|
|
69
|
+
|
|
70
|
+
# Add a named profile
|
|
71
|
+
kctl-vendure config add --profile prod
|
|
72
|
+
|
|
73
|
+
# Switch active profile
|
|
74
|
+
kctl-vendure config use prod
|
|
75
|
+
|
|
76
|
+
# Show current config (secrets masked)
|
|
77
|
+
kctl-vendure config show
|
|
78
|
+
|
|
79
|
+
# Test connectivity
|
|
80
|
+
kctl-vendure config test
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Config Keys
|
|
84
|
+
|
|
85
|
+
| Key | Description |
|
|
86
|
+
|-----|-------------|
|
|
87
|
+
| `url` | Vendure Admin API URL (e.g. `https://shop.example.com/admin-api`) |
|
|
88
|
+
| `admin_username` | Admin user login (email) |
|
|
89
|
+
| `admin_password` | Admin user password |
|
|
90
|
+
|
|
91
|
+
### Profile Example
|
|
92
|
+
|
|
93
|
+
```yaml
|
|
94
|
+
profiles:
|
|
95
|
+
kodemeio:
|
|
96
|
+
vendure:
|
|
97
|
+
url: https://shop.kodeme.io/admin-api
|
|
98
|
+
admin_username: admin@kodeme.io
|
|
99
|
+
admin_password: ${VENDURE_ADMIN_PASSWORD}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## Common Workflows
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
# Fulfill an order
|
|
106
|
+
kctl-vendure orders fulfill 789 --tracking "TRACK123"
|
|
107
|
+
|
|
108
|
+
# Export orders as CSV
|
|
109
|
+
kctl-vendure orders list --format csv > orders.csv
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
## Development
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
cd packages/kctl-vendure
|
|
116
|
+
uv sync --all-extras
|
|
117
|
+
uv run pytest tests/ -v
|
|
118
|
+
uv run mypy src/
|
|
119
|
+
uv run ruff check src/
|
|
120
|
+
```
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "kctl-vendure"
|
|
7
|
+
version = "0.6.2"
|
|
8
|
+
description = "Kodemeio Vendure CLI — manage Vendure e-commerce via GraphQL Admin API"
|
|
9
|
+
requires-python = ">=3.12"
|
|
10
|
+
dependencies = [
|
|
11
|
+
"kctl-lib>=0.7.0",
|
|
12
|
+
"typer>=0.15.0",
|
|
13
|
+
"rich>=13.9.0",
|
|
14
|
+
"pydantic>=2.10.0",
|
|
15
|
+
"pyyaml>=6.0.2",
|
|
16
|
+
"httpx>=0.28.0",
|
|
17
|
+
]
|
|
18
|
+
|
|
19
|
+
[project.optional-dependencies]
|
|
20
|
+
dev = [
|
|
21
|
+
"pytest>=8.3.0",
|
|
22
|
+
"pytest-httpx>=0.35.0",
|
|
23
|
+
"ruff>=0.9.0",
|
|
24
|
+
"mypy>=1.14.0",
|
|
25
|
+
"types-PyYAML>=6.0.0",
|
|
26
|
+
]
|
|
27
|
+
|
|
28
|
+
[project.scripts]
|
|
29
|
+
kctl-vendure = "kctl_vendure.cli:_run"
|
|
30
|
+
|
|
31
|
+
[tool.uv.sources]
|
|
32
|
+
kctl-lib = { workspace = true }
|
|
33
|
+
|
|
34
|
+
[tool.hatch.build.targets.wheel]
|
|
35
|
+
packages = ["src/kctl_vendure"]
|
|
36
|
+
|
|
37
|
+
[tool.ruff]
|
|
38
|
+
target-version = "py312"
|
|
39
|
+
line-length = 120
|
|
40
|
+
|
|
41
|
+
[tool.mypy]
|
|
42
|
+
python_version = "3.12"
|
|
43
|
+
strict = true
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: vendure-admin
|
|
3
|
+
description: >
|
|
4
|
+
Vendure e-commerce management via kctl-vendure CLI.
|
|
5
|
+
MUST use for ANY kctl-vendure operation.
|
|
6
|
+
Triggers on: "vendure, e-commerce, ecommerce, products, orders, customers, shop, payments".
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# kctl-vendure
|
|
10
|
+
|
|
11
|
+
Kodemeio Vendure CLI - manage your Vendure e-commerce instance (products, orders, customers, assets, payments).
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
uv tool install kctl-vendure
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Global Options
|
|
20
|
+
|
|
21
|
+
| Option | Short | Description |
|
|
22
|
+
|--------|-------|-------------|
|
|
23
|
+
| `--json` | | JSON output (shortcut for --format json) |
|
|
24
|
+
| `--quiet` | `-q` | Suppress info messages |
|
|
25
|
+
| `--format` | `-f` | Output format: pretty/json/csv/yaml |
|
|
26
|
+
| `--no-header` | | Omit headers in CSV output |
|
|
27
|
+
| `--debug` | | Enable debug logging |
|
|
28
|
+
| `--profile` | `-p` | Config profile name |
|
|
29
|
+
| `--url` | | API URL override |
|
|
30
|
+
| `--username` | `-u` | Admin username override |
|
|
31
|
+
| `--password` | | Admin password override |
|
|
32
|
+
| `--version` | `-V` | Show version |
|
|
33
|
+
|
|
34
|
+
## Commands
|
|
35
|
+
|
|
36
|
+
### config
|
|
37
|
+
- `kctl-vendure config init` — Initialize CLI configuration
|
|
38
|
+
- `kctl-vendure config show` — Show configuration (passwords masked)
|
|
39
|
+
- `kctl-vendure config test` — Test API connection
|
|
40
|
+
|
|
41
|
+
### products
|
|
42
|
+
- `kctl-vendure products list` — List products
|
|
43
|
+
- `kctl-vendure products get` — Get a single product with variants
|
|
44
|
+
- `kctl-vendure products stock` — Update stock level for a product variant
|
|
45
|
+
|
|
46
|
+
### orders
|
|
47
|
+
- `kctl-vendure orders list` — List orders
|
|
48
|
+
- `kctl-vendure orders get` — Get a single order with line items
|
|
49
|
+
- `kctl-vendure orders fulfill` — Add fulfillment to an order
|
|
50
|
+
- `kctl-vendure orders cancel` — Cancel an order
|
|
51
|
+
|
|
52
|
+
### customers
|
|
53
|
+
- `kctl-vendure customers list` — List customers
|
|
54
|
+
- `kctl-vendure customers get` — Get a single customer with order history
|
|
55
|
+
|
|
56
|
+
### assets
|
|
57
|
+
- `kctl-vendure assets list` — List assets
|
|
58
|
+
- `kctl-vendure assets delete` — Delete an asset
|
|
59
|
+
|
|
60
|
+
### payments
|
|
61
|
+
- `kctl-vendure payments list` — List payments for an order
|
|
62
|
+
- `kctl-vendure payments status` — List available payment methods and their status
|
|
63
|
+
|
|
64
|
+
### doctor
|
|
65
|
+
- `kctl-vendure doctor` — Run diagnostic checks
|
|
66
|
+
|
|
67
|
+
## Configuration
|
|
68
|
+
|
|
69
|
+
Service key: `vendure` in `~/.config/kodemeio/config.yaml`
|
|
70
|
+
|
|
71
|
+
```yaml
|
|
72
|
+
profiles:
|
|
73
|
+
terakidz:
|
|
74
|
+
vendure:
|
|
75
|
+
url: https://shop-api.terakidz.com
|
|
76
|
+
username: admin
|
|
77
|
+
password: <password>
|
|
78
|
+
```
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
"""Main CLI entry point for kctl-vendure."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Annotated
|
|
6
|
+
|
|
7
|
+
import typer
|
|
8
|
+
from kctl_lib import KctlError, handle_cli_error
|
|
9
|
+
|
|
10
|
+
from kctl_vendure import __version__
|
|
11
|
+
from kctl_vendure.commands.assets import app as assets_app
|
|
12
|
+
from kctl_vendure.commands.config_cmd import app as config_app
|
|
13
|
+
from kctl_vendure.commands.customers import app as customers_app
|
|
14
|
+
from kctl_vendure.commands.doctor import app as doctor_app
|
|
15
|
+
from kctl_vendure.commands.orders import app as orders_app
|
|
16
|
+
from kctl_vendure.commands.payments import app as payments_app
|
|
17
|
+
from kctl_vendure.commands.products import app as products_app
|
|
18
|
+
from kctl_vendure.core.callbacks import AppContext
|
|
19
|
+
from kctl_lib.self_update import notify_if_outdated
|
|
20
|
+
from kctl_lib.tui import add_tui_command
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def version_callback(value: bool) -> None:
|
|
24
|
+
if value:
|
|
25
|
+
typer.echo(f"kctl-vendure {__version__}")
|
|
26
|
+
raise typer.Exit()
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
app = typer.Typer(
|
|
30
|
+
name="kctl-vendure",
|
|
31
|
+
help="Kodemeio Vendure CLI - manage your Vendure e-commerce instance.",
|
|
32
|
+
no_args_is_help=True,
|
|
33
|
+
rich_markup_mode="rich",
|
|
34
|
+
pretty_exceptions_enable=False,
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
@app.callback()
|
|
39
|
+
def main(
|
|
40
|
+
ctx: typer.Context,
|
|
41
|
+
json_output: Annotated[bool, typer.Option("--json", help="Output as JSON (shortcut for --format json)")] = False,
|
|
42
|
+
quiet: Annotated[bool, typer.Option("--quiet", "-q", help="Suppress info messages")] = False,
|
|
43
|
+
output_format: Annotated[
|
|
44
|
+
str, typer.Option("--format", "-f", help="Output format: pretty, json, csv, yaml")
|
|
45
|
+
] = "pretty",
|
|
46
|
+
no_header: Annotated[bool, typer.Option("--no-header", help="Omit headers in CSV output")] = False,
|
|
47
|
+
debug: Annotated[bool, typer.Option("--debug", help="Enable debug logging")] = False,
|
|
48
|
+
profile: Annotated[str | None, typer.Option("--profile", "-p", help="Config profile name")] = None,
|
|
49
|
+
url: Annotated[str | None, typer.Option("--url", help="API URL override")] = None,
|
|
50
|
+
username: Annotated[str | None, typer.Option("--username", "-u", help="Admin username override")] = None,
|
|
51
|
+
password: Annotated[str | None, typer.Option("--password", help="Admin password override")] = None,
|
|
52
|
+
version: Annotated[
|
|
53
|
+
bool, typer.Option("--version", "-V", callback=version_callback, is_eager=True, help="Show version")
|
|
54
|
+
] = False,
|
|
55
|
+
) -> None:
|
|
56
|
+
"""Kodemeio Vendure e-commerce CLI."""
|
|
57
|
+
import os
|
|
58
|
+
|
|
59
|
+
if debug:
|
|
60
|
+
os.environ["KCTL_DEBUG"] = "1"
|
|
61
|
+
|
|
62
|
+
effective_format = "json" if json_output else output_format
|
|
63
|
+
|
|
64
|
+
ctx.ensure_object(dict)
|
|
65
|
+
ctx.obj = AppContext(
|
|
66
|
+
json_mode=json_output or effective_format == "json",
|
|
67
|
+
quiet=quiet,
|
|
68
|
+
format=effective_format,
|
|
69
|
+
no_header=no_header,
|
|
70
|
+
debug=debug,
|
|
71
|
+
profile=profile,
|
|
72
|
+
url_override=url,
|
|
73
|
+
username_override=username,
|
|
74
|
+
password_override=password,
|
|
75
|
+
)
|
|
76
|
+
notify_if_outdated(ctx.obj.output, "kctl-vendure", __version__)
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
# ---------------------------------------------------------------------------
|
|
80
|
+
# Command groups
|
|
81
|
+
# ---------------------------------------------------------------------------
|
|
82
|
+
app.add_typer(config_app, name="config")
|
|
83
|
+
app.add_typer(products_app, name="products")
|
|
84
|
+
app.add_typer(orders_app, name="orders")
|
|
85
|
+
app.add_typer(customers_app, name="customers")
|
|
86
|
+
app.add_typer(assets_app, name="assets")
|
|
87
|
+
app.add_typer(payments_app, name="payments")
|
|
88
|
+
app.add_typer(doctor_app, name="doctor")
|
|
89
|
+
add_tui_command(app, service_key="vendure", version=__version__)
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def _run() -> None:
|
|
93
|
+
"""Entry point with error handling."""
|
|
94
|
+
try:
|
|
95
|
+
app()
|
|
96
|
+
except KctlError as e:
|
|
97
|
+
handle_cli_error(e)
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
if __name__ == "__main__":
|
|
101
|
+
_run()
|
|
File without changes
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
"""Asset management commands for Vendure e-commerce."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Annotated
|
|
6
|
+
|
|
7
|
+
import typer
|
|
8
|
+
|
|
9
|
+
from kctl_vendure.core.callbacks import AppContext
|
|
10
|
+
|
|
11
|
+
app = typer.Typer(help="Manage Vendure assets.")
|
|
12
|
+
|
|
13
|
+
# ---------------------------------------------------------------------------
|
|
14
|
+
# GraphQL Operations
|
|
15
|
+
# ---------------------------------------------------------------------------
|
|
16
|
+
|
|
17
|
+
ASSETS_LIST_QUERY = """
|
|
18
|
+
query GetAssets($options: AssetListOptions) {
|
|
19
|
+
assets(options: $options) {
|
|
20
|
+
items {
|
|
21
|
+
id
|
|
22
|
+
name
|
|
23
|
+
type
|
|
24
|
+
fileSize
|
|
25
|
+
mimeType
|
|
26
|
+
source
|
|
27
|
+
preview
|
|
28
|
+
}
|
|
29
|
+
totalItems
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
DELETE_ASSET_MUTATION = """
|
|
35
|
+
mutation DeleteAsset($input: DeleteAssetInput!) {
|
|
36
|
+
deleteAsset(input: $input) {
|
|
37
|
+
result
|
|
38
|
+
message
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
@app.command("list")
|
|
45
|
+
def list_cmd(
|
|
46
|
+
ctx: typer.Context,
|
|
47
|
+
limit: Annotated[int, typer.Option("--limit", "-l", help="Number of assets to return")] = 10,
|
|
48
|
+
skip: Annotated[int, typer.Option("--skip", help="Number of assets to skip")] = 0,
|
|
49
|
+
) -> None:
|
|
50
|
+
"""List assets."""
|
|
51
|
+
c: AppContext = ctx.obj
|
|
52
|
+
out = c.output
|
|
53
|
+
variables = {"options": {"take": limit, "skip": skip}}
|
|
54
|
+
data = c.client.query(ASSETS_LIST_QUERY, variables)
|
|
55
|
+
assets_data = data.get("assets", {})
|
|
56
|
+
items = assets_data.get("items", [])
|
|
57
|
+
total = assets_data.get("totalItems", 0)
|
|
58
|
+
|
|
59
|
+
if c.json_mode:
|
|
60
|
+
out.raw_json({"items": items, "totalItems": total})
|
|
61
|
+
else:
|
|
62
|
+
out.info(f"Assets ({total} total)")
|
|
63
|
+
out.table(items, columns=["id", "name", "type", "fileSize", "mimeType"], title="Assets")
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
@app.command()
|
|
67
|
+
def delete(
|
|
68
|
+
ctx: typer.Context,
|
|
69
|
+
asset_id: Annotated[str, typer.Argument(help="Asset ID")],
|
|
70
|
+
force: Annotated[bool, typer.Option("--force", "-f", help="Skip confirmation and force delete")] = False,
|
|
71
|
+
) -> None:
|
|
72
|
+
"""Delete an asset."""
|
|
73
|
+
c: AppContext = ctx.obj
|
|
74
|
+
out = c.output
|
|
75
|
+
|
|
76
|
+
if not force:
|
|
77
|
+
typer.confirm(f"Delete asset {asset_id}?", abort=True)
|
|
78
|
+
|
|
79
|
+
variables = {"input": {"assetId": asset_id, "force": force}}
|
|
80
|
+
data = c.client.mutate(DELETE_ASSET_MUTATION, variables)
|
|
81
|
+
result = data.get("deleteAsset", {})
|
|
82
|
+
|
|
83
|
+
if c.json_mode:
|
|
84
|
+
out.raw_json(result)
|
|
85
|
+
else:
|
|
86
|
+
if result.get("result") == "DELETED":
|
|
87
|
+
out.success(f"Asset {asset_id} deleted")
|
|
88
|
+
else:
|
|
89
|
+
out.error(f"Delete failed: {result.get('message', 'Unknown error')}")
|
|
90
|
+
raise typer.Exit(1)
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
"""Configuration management commands."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Annotated
|
|
6
|
+
|
|
7
|
+
import typer
|
|
8
|
+
|
|
9
|
+
from kctl_vendure.core.callbacks import AppContext
|
|
10
|
+
from kctl_vendure.core.config import (
|
|
11
|
+
CONFIG_FILE,
|
|
12
|
+
SERVICE_KEY,
|
|
13
|
+
ServiceConfig,
|
|
14
|
+
get_all_services_in_profile,
|
|
15
|
+
get_default_profile,
|
|
16
|
+
get_profile_names,
|
|
17
|
+
resolve_active_profile_name,
|
|
18
|
+
set_default_profile,
|
|
19
|
+
set_service_config,
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
app = typer.Typer(help="Manage CLI configuration and profiles.")
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def _mask(val: str) -> str:
|
|
26
|
+
if not val:
|
|
27
|
+
return "[dim]not set[/dim]"
|
|
28
|
+
return f"{val[:4]}{'*' * max(0, len(val) - 8)}{val[-4:]}" if len(val) > 10 else "****"
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
@app.command()
|
|
32
|
+
def init(
|
|
33
|
+
ctx: typer.Context,
|
|
34
|
+
url: Annotated[str | None, typer.Option("--url")] = None,
|
|
35
|
+
username: Annotated[str | None, typer.Option("--username", "-u")] = None,
|
|
36
|
+
password: Annotated[str | None, typer.Option("--password")] = None,
|
|
37
|
+
name: Annotated[str | None, typer.Option("--name", "-n")] = None,
|
|
38
|
+
) -> None:
|
|
39
|
+
"""Initialize CLI configuration."""
|
|
40
|
+
c: AppContext = ctx.obj
|
|
41
|
+
out = c.output
|
|
42
|
+
profile_name = name or typer.prompt("Profile name", default="kodemeio")
|
|
43
|
+
api_url = url or typer.prompt("Vendure URL (e.g. https://shop.example.com)")
|
|
44
|
+
admin_user = username or typer.prompt("Admin username", default="superadmin")
|
|
45
|
+
admin_pass = password or typer.prompt("Admin password", hide_input=True)
|
|
46
|
+
|
|
47
|
+
svc = ServiceConfig(url=api_url, admin_username=admin_user, admin_password=admin_pass)
|
|
48
|
+
set_service_config(profile_name, svc)
|
|
49
|
+
if len(get_profile_names()) <= 1:
|
|
50
|
+
set_default_profile(profile_name)
|
|
51
|
+
out.success(f"Configuration saved to {CONFIG_FILE}")
|
|
52
|
+
out.kv("Profile", profile_name)
|
|
53
|
+
out.kv("URL", api_url)
|
|
54
|
+
out.kv("Username", admin_user)
|
|
55
|
+
out.kv("Password", _mask(admin_pass))
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
@app.command()
|
|
59
|
+
def show(ctx: typer.Context) -> None:
|
|
60
|
+
"""Show configuration (passwords masked)."""
|
|
61
|
+
c: AppContext = ctx.obj
|
|
62
|
+
out = c.output
|
|
63
|
+
default = get_default_profile()
|
|
64
|
+
sections = [
|
|
65
|
+
(
|
|
66
|
+
"General",
|
|
67
|
+
[
|
|
68
|
+
("Config file", str(CONFIG_FILE)),
|
|
69
|
+
("Default profile", default),
|
|
70
|
+
("Service key", SERVICE_KEY),
|
|
71
|
+
],
|
|
72
|
+
)
|
|
73
|
+
]
|
|
74
|
+
for pname in get_profile_names():
|
|
75
|
+
marker = " [green](default)[/green]" if pname == default else ""
|
|
76
|
+
services = get_all_services_in_profile(pname)
|
|
77
|
+
kvs = []
|
|
78
|
+
for svc_name, svc_data in services.items():
|
|
79
|
+
if not isinstance(svc_data, dict):
|
|
80
|
+
continue
|
|
81
|
+
indicator = "[green]●[/green]" if svc_name == SERVICE_KEY else "[dim]○[/dim]"
|
|
82
|
+
kvs.append(
|
|
83
|
+
(
|
|
84
|
+
f"{indicator} {svc_name}",
|
|
85
|
+
f"{svc_data.get('url', '')} user: {svc_data.get('admin_username', '')} pass: {_mask(svc_data.get('admin_password', ''))}",
|
|
86
|
+
)
|
|
87
|
+
)
|
|
88
|
+
sections.append((f"Profile: {pname}{marker}", kvs or [("(empty)", "")]))
|
|
89
|
+
out.detail("Configuration", sections)
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
@app.command()
|
|
93
|
+
def test(ctx: typer.Context) -> None:
|
|
94
|
+
"""Test API connection."""
|
|
95
|
+
c: AppContext = ctx.obj
|
|
96
|
+
out = c.output
|
|
97
|
+
active = resolve_active_profile_name(c.profile)
|
|
98
|
+
out.info(f"Testing profile '{active}' -> {SERVICE_KEY}")
|
|
99
|
+
try:
|
|
100
|
+
status = c.client.check_health()
|
|
101
|
+
if status == 200:
|
|
102
|
+
out.success("Connected to Vendure API")
|
|
103
|
+
else:
|
|
104
|
+
out.error(f"Connection failed: HTTP {status}")
|
|
105
|
+
raise typer.Exit(1)
|
|
106
|
+
except Exception as e:
|
|
107
|
+
out.error(f"Connection failed: {e}")
|
|
108
|
+
raise typer.Exit(1) from e
|