botu-cli 0.2.0__tar.gz → 0.3.0__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.
- {botu_cli-0.2.0 → botu_cli-0.3.0}/PKG-INFO +1 -1
- {botu_cli-0.2.0 → botu_cli-0.3.0}/pyproject.toml +1 -1
- {botu_cli-0.2.0 → botu_cli-0.3.0}/src/botu_cli/__main__.py +86 -0
- {botu_cli-0.2.0 → botu_cli-0.3.0}/.gitignore +0 -0
- {botu_cli-0.2.0 → botu_cli-0.3.0}/README.md +0 -0
- {botu_cli-0.2.0 → botu_cli-0.3.0}/src/botu_cli/__init__.py +0 -0
- {botu_cli-0.2.0 → botu_cli-0.3.0}/src/botu_cli/product.py +0 -0
- {botu_cli-0.2.0 → botu_cli-0.3.0}/tests/__init__.py +0 -0
- {botu_cli-0.2.0 → botu_cli-0.3.0}/tests/test_cli.py +0 -0
|
@@ -196,6 +196,92 @@ def sites_get(site_id: str = typer.Argument(..., help="Site id (uuid).")) -> Non
|
|
|
196
196
|
emit(out)
|
|
197
197
|
|
|
198
198
|
|
|
199
|
+
@sites_app.command("update")
|
|
200
|
+
def sites_update(
|
|
201
|
+
site_id: str = typer.Argument(..., help="Site id (uuid)."),
|
|
202
|
+
name: str = typer.Option(None, "--name", "-n", help="New name."),
|
|
203
|
+
description: str = typer.Option(None, "--description", help="New description."),
|
|
204
|
+
add_origin: list[str] = typer.Option(
|
|
205
|
+
None,
|
|
206
|
+
"--add-origin",
|
|
207
|
+
help="Add an allowed origin (repeatable). Merges with existing origins.",
|
|
208
|
+
),
|
|
209
|
+
remove_origin: list[str] = typer.Option(
|
|
210
|
+
None,
|
|
211
|
+
"--remove-origin",
|
|
212
|
+
help="Remove an allowed origin (repeatable). Merges with existing origins.",
|
|
213
|
+
),
|
|
214
|
+
set_origins: list[str] = typer.Option(
|
|
215
|
+
None,
|
|
216
|
+
"--set-origin",
|
|
217
|
+
help=(
|
|
218
|
+
"Replace allowed origins (repeatable). Mutually exclusive with "
|
|
219
|
+
"--add-origin / --remove-origin."
|
|
220
|
+
),
|
|
221
|
+
),
|
|
222
|
+
theme_mode: str = typer.Option(
|
|
223
|
+
None,
|
|
224
|
+
"--theme-mode",
|
|
225
|
+
help="Theme detection mode: auto | light | dark.",
|
|
226
|
+
),
|
|
227
|
+
theme_target: str = typer.Option(
|
|
228
|
+
None,
|
|
229
|
+
"--theme-target",
|
|
230
|
+
help="Theme target element selector: html | body | <custom-css-selector>.",
|
|
231
|
+
),
|
|
232
|
+
) -> None:
|
|
233
|
+
"""Update an existing site (name / description / allowed origins / theme).
|
|
234
|
+
|
|
235
|
+
Origins:
|
|
236
|
+
• --add-origin / --remove-origin merge against the current allowlist
|
|
237
|
+
(1 GET + 1 PATCH); use these for incremental changes.
|
|
238
|
+
• --set-origin replaces the list outright. Mixing modes is an error.
|
|
239
|
+
"""
|
|
240
|
+
if set_origins and (add_origin or remove_origin):
|
|
241
|
+
_fail(
|
|
242
|
+
ApiError(
|
|
243
|
+
400,
|
|
244
|
+
"--set-origin cannot combine with --add-origin / --remove-origin",
|
|
245
|
+
)
|
|
246
|
+
)
|
|
247
|
+
|
|
248
|
+
patch: dict = {}
|
|
249
|
+
if name is not None:
|
|
250
|
+
patch["name"] = name
|
|
251
|
+
if description is not None:
|
|
252
|
+
patch["description"] = description
|
|
253
|
+
if theme_mode is not None or theme_target is not None:
|
|
254
|
+
patch["themeStrategy"] = {
|
|
255
|
+
**({"mode": theme_mode} if theme_mode is not None else {}),
|
|
256
|
+
**({"target": theme_target} if theme_target is not None else {}),
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
needs_origin_merge = bool(add_origin or remove_origin)
|
|
260
|
+
if set_origins:
|
|
261
|
+
patch["allowedOrigins"] = [o.strip() for o in set_origins if o and o.strip()]
|
|
262
|
+
elif needs_origin_merge:
|
|
263
|
+
try:
|
|
264
|
+
current = api("GET", f"/api/sites/{site_id}")
|
|
265
|
+
except ApiError as e:
|
|
266
|
+
_fail(e)
|
|
267
|
+
existing = list((current.get("site") or {}).get("allowed_origins") or [])
|
|
268
|
+
merged = [o for o in existing if o not in (remove_origin or [])]
|
|
269
|
+
for o in add_origin or []:
|
|
270
|
+
o_clean = o.strip()
|
|
271
|
+
if o_clean and o_clean not in merged:
|
|
272
|
+
merged.append(o_clean)
|
|
273
|
+
patch["allowedOrigins"] = merged
|
|
274
|
+
|
|
275
|
+
if not patch:
|
|
276
|
+
_fail(ApiError(400, "nothing to update — supply at least one field"))
|
|
277
|
+
|
|
278
|
+
try:
|
|
279
|
+
out = api("PATCH", f"/api/sites/{site_id}", patch)
|
|
280
|
+
except ApiError as e:
|
|
281
|
+
_fail(e)
|
|
282
|
+
emit(out)
|
|
283
|
+
|
|
284
|
+
|
|
199
285
|
@sites_app.command("delete")
|
|
200
286
|
def sites_delete(
|
|
201
287
|
site_id: str = typer.Argument(..., help="Site id (uuid)."),
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|