makea-cli 0.1.16__tar.gz → 0.1.17__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.
- {makea_cli-0.1.16 → makea_cli-0.1.17}/PKG-INFO +1 -1
- makea_cli-0.1.17/makea_cli/__init__.py +1 -0
- {makea_cli-0.1.16 → makea_cli-0.1.17}/makea_cli/api_client.py +74 -0
- {makea_cli-0.1.16 → makea_cli-0.1.17}/makea_cli/commands/__init__.py +2 -0
- makea_cli-0.1.17/makea_cli/commands/library/cmd.py +281 -0
- makea_cli-0.1.17/makea_cli/commands/metrics/__init__.py +0 -0
- {makea_cli-0.1.16 → makea_cli-0.1.17}/pyproject.toml +1 -1
- makea_cli-0.1.16/makea_cli/__init__.py +0 -1
- {makea_cli-0.1.16 → makea_cli-0.1.17}/.claude/skills/create-supplier-profile/SKILL.md +0 -0
- {makea_cli-0.1.16 → makea_cli-0.1.17}/.claude/skills/lark-cli-setup/SKILL.md +0 -0
- {makea_cli-0.1.16 → makea_cli-0.1.17}/.claude/skills/link-supplier-user/SKILL.md +0 -0
- {makea_cli-0.1.16 → makea_cli-0.1.17}/.claude/skills/makea-cli-setup/SKILL.md +0 -0
- {makea_cli-0.1.16 → makea_cli-0.1.17}/.claude/skills/payment-revenue-report/SKILL.md +0 -0
- {makea_cli-0.1.16 → makea_cli-0.1.17}/.claude/skills/supplier-user-id-migration/SKILL.md +0 -0
- {makea_cli-0.1.16 → makea_cli-0.1.17}/.gitignore +0 -0
- {makea_cli-0.1.16 → makea_cli-0.1.17}/README.md +0 -0
- {makea_cli-0.1.16 → makea_cli-0.1.17}/makea-collection-upload/SKILL.md +0 -0
- {makea_cli-0.1.16 → makea_cli-0.1.17}/makea-collection-upload/scripts/create_products.py +0 -0
- {makea_cli-0.1.16 → makea_cli-0.1.17}/makea_cli/__main__.py +0 -0
- {makea_cli-0.1.16 → makea_cli-0.1.17}/makea_cli/auth_pkce.py +0 -0
- {makea_cli-0.1.16 → makea_cli-0.1.17}/makea_cli/commands/_util.py +0 -0
- {makea_cli-0.1.16 → makea_cli-0.1.17}/makea_cli/commands/analytics/__init__.py +0 -0
- {makea_cli-0.1.16 → makea_cli-0.1.17}/makea_cli/commands/analytics/cmd.py +0 -0
- {makea_cli-0.1.16 → makea_cli-0.1.17}/makea_cli/commands/auth/__init__.py +0 -0
- {makea_cli-0.1.16 → makea_cli-0.1.17}/makea_cli/commands/auth/cmd.py +0 -0
- {makea_cli-0.1.16 → makea_cli-0.1.17}/makea_cli/commands/designer/__init__.py +0 -0
- {makea_cli-0.1.16 → makea_cli-0.1.17}/makea_cli/commands/designer/cmd.py +0 -0
- {makea_cli-0.1.16 → makea_cli-0.1.17}/makea_cli/commands/directory/__init__.py +0 -0
- {makea_cli-0.1.16 → makea_cli-0.1.17}/makea_cli/commands/directory/cmd.py +0 -0
- {makea_cli-0.1.16 → makea_cli-0.1.17}/makea_cli/commands/document/__init__.py +0 -0
- {makea_cli-0.1.16 → makea_cli-0.1.17}/makea_cli/commands/document/cmd.py +0 -0
- {makea_cli-0.1.16 → makea_cli-0.1.17}/makea_cli/commands/email/__init__.py +0 -0
- {makea_cli-0.1.16 → makea_cli-0.1.17}/makea_cli/commands/email/cmd.py +0 -0
- {makea_cli-0.1.16/makea_cli/commands/metrics → makea_cli-0.1.17/makea_cli/commands/library}/__init__.py +0 -0
- {makea_cli-0.1.16 → makea_cli-0.1.17}/makea_cli/commands/metrics/cmd.py +0 -0
- {makea_cli-0.1.16 → makea_cli-0.1.17}/makea_cli/commands/orders/__init__.py +0 -0
- {makea_cli-0.1.16 → makea_cli-0.1.17}/makea_cli/commands/orders/cmd.py +0 -0
- {makea_cli-0.1.16 → makea_cli-0.1.17}/makea_cli/commands/product/__init__.py +0 -0
- {makea_cli-0.1.16 → makea_cli-0.1.17}/makea_cli/commands/product/cmd.py +0 -0
- {makea_cli-0.1.16 → makea_cli-0.1.17}/makea_cli/commands/supplier/__init__.py +0 -0
- {makea_cli-0.1.16 → makea_cli-0.1.17}/makea_cli/commands/supplier/cmd.py +0 -0
- {makea_cli-0.1.16 → makea_cli-0.1.17}/makea_cli/config.py +0 -0
- {makea_cli-0.1.16 → makea_cli-0.1.17}/makea_cli/main.py +0 -0
- {makea_cli-0.1.16 → makea_cli-0.1.17}/makea_cli/posthog_client.py +0 -0
- {makea_cli-0.1.16 → makea_cli-0.1.17}/npm/makea-cli/README.md +0 -0
- {makea_cli-0.1.16 → makea_cli-0.1.17}/npm/makea-cli/makea-cli.mjs +0 -0
- {makea_cli-0.1.16 → makea_cli-0.1.17}/npm/makea-cli/package.json +0 -0
- {makea_cli-0.1.16 → makea_cli-0.1.17}/uv.lock +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.1.17"
|
|
@@ -79,6 +79,35 @@ def put_json(path: str, body: Any, *, timeout: float = 60.0) -> Any:
|
|
|
79
79
|
return r.json()
|
|
80
80
|
|
|
81
81
|
|
|
82
|
+
def patch_json(path: str, body: Any, *, timeout: float = 60.0) -> Any:
|
|
83
|
+
"""PATCH JSON body (same error handling as ``post_json``)."""
|
|
84
|
+
url = f"{api_base_url()}{path}"
|
|
85
|
+
headers = {**_headers(), "Content-Type": "application/json"}
|
|
86
|
+
with httpx.Client(timeout=timeout) as client:
|
|
87
|
+
r = client.patch(url, headers=headers, json=body)
|
|
88
|
+
if r.status_code >= 400:
|
|
89
|
+
try:
|
|
90
|
+
detail = r.json()
|
|
91
|
+
except json.JSONDecodeError:
|
|
92
|
+
detail = r.text
|
|
93
|
+
raise RuntimeError(f"HTTP {r.status_code}: {detail}")
|
|
94
|
+
return r.json()
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def delete_json(path: str, *, params: dict[str, Any] | None = None, timeout: float = 60.0) -> Any:
|
|
98
|
+
"""DELETE request (same error handling as ``get_json``)."""
|
|
99
|
+
url = f"{api_base_url()}{path}"
|
|
100
|
+
with httpx.Client(timeout=timeout) as client:
|
|
101
|
+
r = client.delete(url, headers=_headers(), params=params)
|
|
102
|
+
if r.status_code >= 400:
|
|
103
|
+
try:
|
|
104
|
+
detail = r.json()
|
|
105
|
+
except json.JSONDecodeError:
|
|
106
|
+
detail = r.text
|
|
107
|
+
raise RuntimeError(f"HTTP {r.status_code}: {detail}")
|
|
108
|
+
return r.json()
|
|
109
|
+
|
|
110
|
+
|
|
82
111
|
def send_admin_raw_email(body: dict[str, Any]) -> Any:
|
|
83
112
|
"""
|
|
84
113
|
POST /admin/email/send — queue HTML email (from must be @makea.co).
|
|
@@ -816,3 +845,48 @@ def update_product_technical_specifications(
|
|
|
816
845
|
{"technical_specifications": json.dumps(technical_specifications)},
|
|
817
846
|
timeout=timeout,
|
|
818
847
|
)
|
|
848
|
+
|
|
849
|
+
|
|
850
|
+
# ── Tech-pack library (reusable library components), admin-side ──────────
|
|
851
|
+
def admin_library_component_schema(*, timeout: float = 60.0) -> Any:
|
|
852
|
+
"""GET /admin/library_components/schema — the library taxonomy (sections +
|
|
853
|
+
library-role field descriptors). Static; no target user."""
|
|
854
|
+
return get_json("/admin/library_components/schema", timeout=timeout)
|
|
855
|
+
|
|
856
|
+
|
|
857
|
+
def admin_list_library_components(
|
|
858
|
+
user_id: str, *, section: str | None = None, timeout: float = 60.0
|
|
859
|
+
) -> Any:
|
|
860
|
+
"""GET /admin/designer/{user_id}/library_components — list a designer's
|
|
861
|
+
tech-pack library (org-fanned). Optional ``section`` scopes to one type."""
|
|
862
|
+
params = {"section": section} if section else None
|
|
863
|
+
return get_json(f"/admin/designer/{user_id}/library_components", params=params, timeout=timeout)
|
|
864
|
+
|
|
865
|
+
|
|
866
|
+
def admin_create_library_component(
|
|
867
|
+
user_id: str, body: dict[str, Any], *, timeout: float = 60.0
|
|
868
|
+
) -> Any:
|
|
869
|
+
"""POST /admin/designer/{user_id}/library_components — {section, name?,
|
|
870
|
+
values, documents?}."""
|
|
871
|
+
return post_json(f"/admin/designer/{user_id}/library_components", body, timeout=timeout)
|
|
872
|
+
|
|
873
|
+
|
|
874
|
+
def admin_update_library_component(
|
|
875
|
+
user_id: str, component_id: str, body: dict[str, Any], *, timeout: float = 60.0
|
|
876
|
+
) -> Any:
|
|
877
|
+
"""PATCH /admin/designer/{user_id}/library_components/{component_id} —
|
|
878
|
+
{name?, values?, documents?}."""
|
|
879
|
+
return patch_json(
|
|
880
|
+
f"/admin/designer/{user_id}/library_components/{component_id}",
|
|
881
|
+
body,
|
|
882
|
+
timeout=timeout,
|
|
883
|
+
)
|
|
884
|
+
|
|
885
|
+
|
|
886
|
+
def admin_delete_library_component(
|
|
887
|
+
user_id: str, component_id: str, *, timeout: float = 60.0
|
|
888
|
+
) -> Any:
|
|
889
|
+
"""DELETE /admin/designer/{user_id}/library_components/{component_id}."""
|
|
890
|
+
return delete_json(
|
|
891
|
+
f"/admin/designer/{user_id}/library_components/{component_id}", timeout=timeout
|
|
892
|
+
)
|
|
@@ -8,6 +8,7 @@ from makea_cli.commands.designer.cmd import register as register_designer
|
|
|
8
8
|
from makea_cli.commands.directory.cmd import register as register_directory
|
|
9
9
|
from makea_cli.commands.document.cmd import register as register_document
|
|
10
10
|
from makea_cli.commands.email.cmd import register as register_email
|
|
11
|
+
from makea_cli.commands.library.cmd import register as register_library
|
|
11
12
|
from makea_cli.commands.metrics.cmd import register as register_metrics
|
|
12
13
|
from makea_cli.commands.orders.cmd import register as register_orders
|
|
13
14
|
from makea_cli.commands.product.cmd import register as register_product
|
|
@@ -25,3 +26,4 @@ def register_all(app: typer.Typer) -> None:
|
|
|
25
26
|
register_metrics(app)
|
|
26
27
|
register_analytics(app)
|
|
27
28
|
register_email(app)
|
|
29
|
+
register_library(app)
|
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
"""Admin commands for a designer's tech-pack library (reusable library components).
|
|
2
|
+
|
|
3
|
+
A *library component* is a designer's saved, reusable spec for one tech-pack
|
|
4
|
+
section — the ``role='library'`` field values of a fabric / colour / trim …
|
|
5
|
+
(name, composition, construction, certifications, pricing). Designers fill them
|
|
6
|
+
into tech packs ("use from library") and capture them back ("save to library");
|
|
7
|
+
the library is shared across their org the same way products are.
|
|
8
|
+
|
|
9
|
+
These commands are the admin side: they take the target designer's ``user_id``
|
|
10
|
+
explicitly (Cognito sub) and curate that designer/org's library on their behalf.
|
|
11
|
+
Require an admin Makea login (makea-cli auth).
|
|
12
|
+
|
|
13
|
+
Workflow: run ``library-schema`` first to learn the valid ``section`` ids and the
|
|
14
|
+
``values`` keys (and which are required) before ``library-create`` / ``library-update``.
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
from __future__ import annotations
|
|
18
|
+
|
|
19
|
+
import json
|
|
20
|
+
from pathlib import Path
|
|
21
|
+
from typing import Any
|
|
22
|
+
|
|
23
|
+
import typer
|
|
24
|
+
from rich.console import Console
|
|
25
|
+
|
|
26
|
+
from makea_cli import api_client
|
|
27
|
+
from makea_cli.commands._util import print_json_or_exit
|
|
28
|
+
|
|
29
|
+
console = Console()
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
_LIBRARY_EPILOG = """
|
|
33
|
+
The tech-pack library holds reusable per-section specs (fabrics, colours, trims …)
|
|
34
|
+
keyed to a designer and shared across their org.
|
|
35
|
+
|
|
36
|
+
Taxonomy first
|
|
37
|
+
Run ``makea-cli library-schema`` to list the sections that support a library
|
|
38
|
+
(e.g. MAIN_FABRIC) and, per section, the ``values`` keys, their labels/types,
|
|
39
|
+
and which are required ("essential") before a component can be saved. The
|
|
40
|
+
server ignores any ``values`` key that is not a library-role field for the
|
|
41
|
+
section, so use exactly the keys the schema reports.
|
|
42
|
+
|
|
43
|
+
Creating / updating
|
|
44
|
+
``values`` is an object of ``{"<field key>": <value>}`` — e.g.
|
|
45
|
+
``{"main_fabric.library.name": "Pique Knit", "main_fabric.library.composition": "100% Cotton"}``.
|
|
46
|
+
On update, a provided value replaces; an empty string / null clears that field.
|
|
47
|
+
A component's display name defaults to its ``*.library.name`` value when ``name``
|
|
48
|
+
is omitted.
|
|
49
|
+
|
|
50
|
+
Org scope
|
|
51
|
+
Reads (``library-list``) fan across the target designer's whole org and tag each
|
|
52
|
+
component with ``owner_user_id``. Creates land under the USER_ID you pass;
|
|
53
|
+
update/delete work on any component in that user's org.
|
|
54
|
+
""".strip()
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def _load_values(values: str | None, values_file: Path | None) -> dict[str, Any]:
|
|
58
|
+
"""Resolve the ``values`` map from an inline JSON string or a JSON file."""
|
|
59
|
+
if values is not None and values_file is not None:
|
|
60
|
+
raise ValueError("Pass only one of --values / --values-file.")
|
|
61
|
+
raw: str | None = None
|
|
62
|
+
if values_file is not None:
|
|
63
|
+
raw = values_file.read_text(encoding="utf-8")
|
|
64
|
+
elif values is not None:
|
|
65
|
+
raw = values
|
|
66
|
+
if raw is None:
|
|
67
|
+
return {}
|
|
68
|
+
parsed = json.loads(raw)
|
|
69
|
+
if not isinstance(parsed, dict):
|
|
70
|
+
raise ValueError("values must be a JSON object of {field key: value}.")
|
|
71
|
+
return parsed
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def register(app: typer.Typer) -> None:
|
|
75
|
+
@app.command(
|
|
76
|
+
"library-schema",
|
|
77
|
+
help=(
|
|
78
|
+
"GET /admin/library_components/schema — the tech-pack library taxonomy: "
|
|
79
|
+
"sections and their library-role field keys (run this before create/update)."
|
|
80
|
+
),
|
|
81
|
+
epilog=_LIBRARY_EPILOG,
|
|
82
|
+
)
|
|
83
|
+
def library_schema(
|
|
84
|
+
timeout: float = typer.Option(
|
|
85
|
+
60.0,
|
|
86
|
+
"--timeout",
|
|
87
|
+
"-t",
|
|
88
|
+
help="HTTP timeout in seconds.",
|
|
89
|
+
min=10.0,
|
|
90
|
+
max=300.0,
|
|
91
|
+
),
|
|
92
|
+
) -> None:
|
|
93
|
+
"""Print the library taxonomy (sections + fields). Admin token required."""
|
|
94
|
+
print_json_or_exit(
|
|
95
|
+
console,
|
|
96
|
+
lambda: api_client.admin_library_component_schema(timeout=timeout),
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
@app.command(
|
|
100
|
+
"library-list",
|
|
101
|
+
help=(
|
|
102
|
+
"GET /admin/designer/{user_id}/library_components — list a designer's "
|
|
103
|
+
"tech-pack library (org-fanned). Optional --section scopes to one type."
|
|
104
|
+
),
|
|
105
|
+
epilog=_LIBRARY_EPILOG,
|
|
106
|
+
)
|
|
107
|
+
def library_list(
|
|
108
|
+
user_id: str = typer.Argument(..., help="Target designer Cognito user_id (sub)."),
|
|
109
|
+
section: str | None = typer.Option(
|
|
110
|
+
None,
|
|
111
|
+
"--section",
|
|
112
|
+
"-s",
|
|
113
|
+
help="Scope to one section id (e.g. MAIN_FABRIC); see library-schema.",
|
|
114
|
+
),
|
|
115
|
+
timeout: float = typer.Option(
|
|
116
|
+
60.0,
|
|
117
|
+
"--timeout",
|
|
118
|
+
"-t",
|
|
119
|
+
help="HTTP timeout in seconds.",
|
|
120
|
+
min=10.0,
|
|
121
|
+
max=300.0,
|
|
122
|
+
),
|
|
123
|
+
) -> None:
|
|
124
|
+
"""List the target designer's library components across their org."""
|
|
125
|
+
print_json_or_exit(
|
|
126
|
+
console,
|
|
127
|
+
lambda: api_client.admin_list_library_components(
|
|
128
|
+
user_id, section=section, timeout=timeout
|
|
129
|
+
),
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
@app.command(
|
|
133
|
+
"library-create",
|
|
134
|
+
help=(
|
|
135
|
+
"POST /admin/designer/{user_id}/library_components — save a reusable "
|
|
136
|
+
"component under a designer. Provide --section and --values (see library-schema)."
|
|
137
|
+
),
|
|
138
|
+
epilog=_LIBRARY_EPILOG,
|
|
139
|
+
)
|
|
140
|
+
def library_create(
|
|
141
|
+
user_id: str = typer.Argument(..., help="Target designer Cognito user_id (sub)."),
|
|
142
|
+
section: str = typer.Option(
|
|
143
|
+
...,
|
|
144
|
+
"--section",
|
|
145
|
+
"-s",
|
|
146
|
+
help="Section id the component belongs to (e.g. MAIN_FABRIC).",
|
|
147
|
+
),
|
|
148
|
+
name: str | None = typer.Option(
|
|
149
|
+
None,
|
|
150
|
+
"--name",
|
|
151
|
+
"-n",
|
|
152
|
+
help="Optional display name (defaults to the *.library.name value).",
|
|
153
|
+
),
|
|
154
|
+
values: str | None = typer.Option(
|
|
155
|
+
None,
|
|
156
|
+
"--values",
|
|
157
|
+
help='Inline JSON object of {field key: value}, e.g. \'{"main_fabric.library.name":"Pique Knit"}\'.',
|
|
158
|
+
),
|
|
159
|
+
values_file: Path | None = typer.Option(
|
|
160
|
+
None,
|
|
161
|
+
"--values-file",
|
|
162
|
+
"-f",
|
|
163
|
+
exists=True,
|
|
164
|
+
dir_okay=False,
|
|
165
|
+
readable=True,
|
|
166
|
+
help="Path to a UTF-8 JSON file holding the values object (instead of --values).",
|
|
167
|
+
),
|
|
168
|
+
timeout: float = typer.Option(
|
|
169
|
+
60.0,
|
|
170
|
+
"--timeout",
|
|
171
|
+
"-t",
|
|
172
|
+
help="HTTP timeout in seconds.",
|
|
173
|
+
min=10.0,
|
|
174
|
+
max=300.0,
|
|
175
|
+
),
|
|
176
|
+
) -> None:
|
|
177
|
+
"""Create a library component under the target designer."""
|
|
178
|
+
try:
|
|
179
|
+
body: dict[str, Any] = {
|
|
180
|
+
"section": section,
|
|
181
|
+
"values": _load_values(values, values_file),
|
|
182
|
+
}
|
|
183
|
+
if name is not None:
|
|
184
|
+
body["name"] = name
|
|
185
|
+
except (OSError, json.JSONDecodeError, ValueError) as e:
|
|
186
|
+
console.print(f"[red]Invalid input: {e}[/red]")
|
|
187
|
+
raise typer.Exit(1) from e
|
|
188
|
+
|
|
189
|
+
print_json_or_exit(
|
|
190
|
+
console,
|
|
191
|
+
lambda: api_client.admin_create_library_component(user_id, body, timeout=timeout),
|
|
192
|
+
)
|
|
193
|
+
|
|
194
|
+
@app.command(
|
|
195
|
+
"library-update",
|
|
196
|
+
help=(
|
|
197
|
+
"PATCH /admin/designer/{user_id}/library_components/{component_id} — update "
|
|
198
|
+
"a component's name and/or values (empty value clears a field)."
|
|
199
|
+
),
|
|
200
|
+
epilog=_LIBRARY_EPILOG,
|
|
201
|
+
)
|
|
202
|
+
def library_update(
|
|
203
|
+
user_id: str = typer.Argument(..., help="Target designer Cognito user_id (sub)."),
|
|
204
|
+
component_id: str = typer.Argument(..., help="Library component UUID."),
|
|
205
|
+
name: str | None = typer.Option(None, "--name", "-n", help="New display name."),
|
|
206
|
+
values: str | None = typer.Option(
|
|
207
|
+
None,
|
|
208
|
+
"--values",
|
|
209
|
+
help='Inline JSON object of {field key: value} to merge; "" or null clears a field.',
|
|
210
|
+
),
|
|
211
|
+
values_file: Path | None = typer.Option(
|
|
212
|
+
None,
|
|
213
|
+
"--values-file",
|
|
214
|
+
"-f",
|
|
215
|
+
exists=True,
|
|
216
|
+
dir_okay=False,
|
|
217
|
+
readable=True,
|
|
218
|
+
help="Path to a UTF-8 JSON file holding the values object (instead of --values).",
|
|
219
|
+
),
|
|
220
|
+
timeout: float = typer.Option(
|
|
221
|
+
60.0,
|
|
222
|
+
"--timeout",
|
|
223
|
+
"-t",
|
|
224
|
+
help="HTTP timeout in seconds.",
|
|
225
|
+
min=10.0,
|
|
226
|
+
max=300.0,
|
|
227
|
+
),
|
|
228
|
+
) -> None:
|
|
229
|
+
"""Update a library component's name and/or values."""
|
|
230
|
+
try:
|
|
231
|
+
body: dict[str, Any] = {}
|
|
232
|
+
if name is not None:
|
|
233
|
+
body["name"] = name
|
|
234
|
+
if values is not None or values_file is not None:
|
|
235
|
+
body["values"] = _load_values(values, values_file)
|
|
236
|
+
if not body:
|
|
237
|
+
raise ValueError("Nothing to update: pass --name and/or --values.")
|
|
238
|
+
except (OSError, json.JSONDecodeError, ValueError) as e:
|
|
239
|
+
console.print(f"[red]Invalid input: {e}[/red]")
|
|
240
|
+
raise typer.Exit(1) from e
|
|
241
|
+
|
|
242
|
+
print_json_or_exit(
|
|
243
|
+
console,
|
|
244
|
+
lambda: api_client.admin_update_library_component(
|
|
245
|
+
user_id, component_id, body, timeout=timeout
|
|
246
|
+
),
|
|
247
|
+
)
|
|
248
|
+
|
|
249
|
+
@app.command(
|
|
250
|
+
"library-delete",
|
|
251
|
+
help=(
|
|
252
|
+
"DELETE /admin/designer/{user_id}/library_components/{component_id} — remove "
|
|
253
|
+
"a component from the designer's org library."
|
|
254
|
+
),
|
|
255
|
+
epilog=_LIBRARY_EPILOG,
|
|
256
|
+
)
|
|
257
|
+
def library_delete(
|
|
258
|
+
user_id: str = typer.Argument(..., help="Target designer Cognito user_id (sub)."),
|
|
259
|
+
component_id: str = typer.Argument(..., help="Library component UUID."),
|
|
260
|
+
yes: bool = typer.Option(False, "--yes", "-y", help="Skip the confirmation prompt."),
|
|
261
|
+
timeout: float = typer.Option(
|
|
262
|
+
60.0,
|
|
263
|
+
"--timeout",
|
|
264
|
+
"-t",
|
|
265
|
+
help="HTTP timeout in seconds.",
|
|
266
|
+
min=10.0,
|
|
267
|
+
max=300.0,
|
|
268
|
+
),
|
|
269
|
+
) -> None:
|
|
270
|
+
"""Delete a library component from the target designer's org library."""
|
|
271
|
+
if not yes:
|
|
272
|
+
typer.confirm(
|
|
273
|
+
f"Delete library component {component_id} from {user_id}'s org library?",
|
|
274
|
+
abort=True,
|
|
275
|
+
)
|
|
276
|
+
print_json_or_exit(
|
|
277
|
+
console,
|
|
278
|
+
lambda: api_client.admin_delete_library_component(
|
|
279
|
+
user_id, component_id, timeout=timeout
|
|
280
|
+
),
|
|
281
|
+
)
|
|
File without changes
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.1.16"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|