206 lines
6.6 KiB
Markdown
206 lines
6.6 KiB
Markdown
# cmsctl
|
|
|
|
`cmsctl` is a dependency-free Go CLI for the platform's backoffice APIs. It
|
|
uses the existing RFC 8628 device-login flow and stores the resulting bearer
|
|
token **together with the instance base URL** in:
|
|
|
|
- `$CMSCTL_CONFIG`, when set
|
|
- `$XDG_CONFIG_HOME/cmsctl/config.json`, when set
|
|
- the platform config directory from Go's `os.UserConfigDir()` otherwise:
|
|
- Unix/Linux: `~/.config/cmsctl/config.json`
|
|
- macOS: `~/Library/Application Support/cmsctl/config.json`
|
|
- Windows: `%AppData%\\cmsctl\\config.json`
|
|
|
|
The persisted JSON uses `base_url` for the instance URL and `access_token` for
|
|
the device token.
|
|
|
|
The file and its parent directory are created with restrictive permissions
|
|
(`0700`/`0600`). The token is never printed during login; login progress goes to
|
|
stderr so stdout remains pipe-safe.
|
|
|
|
## Build and run
|
|
|
|
From `platform/`:
|
|
|
|
```bash
|
|
go build -o cmsctl ./cmd/cmsctl
|
|
go run ./cmd/cmsctl --help
|
|
```
|
|
|
|
The default backoffice URL is `http://localhost:8080`.
|
|
|
|
## Authenticate
|
|
|
|
```bash
|
|
cmsctl auth login --scope read,write
|
|
# Open the displayed verification URL and approve the code as an admin.
|
|
|
|
cmsctl auth status
|
|
cmsctl auth token --raw | secret-tool store --label=cmsctl token
|
|
cmsctl auth logout
|
|
```
|
|
|
|
The token can also be supplied per invocation with `--token` or
|
|
`CMSCTL_TOKEN`; a minted API key can be supplied with `--api-key` or
|
|
`CMSCTL_API_KEY`.
|
|
|
|
Global connection flags must appear before the command:
|
|
|
|
```bash
|
|
cmsctl --base-url https://shop.example cms nodes list --type page
|
|
cmsctl --finder-url http://finder:8080 finder search --q drill
|
|
cmsctl finder import inventory.json
|
|
```
|
|
|
|
When `--finder-url` is omitted, finder reads use `<base-url>/find`, which is the
|
|
backoffice proxy. Finder administration always uses `<base-url>/catalog/admin`.
|
|
The CLI intentionally has no separate finder-admin URL: the backoffice is the
|
|
writeradmin boundary.
|
|
|
|
## CMS
|
|
|
|
```bash
|
|
cmsctl cms nodes list --type page --limit 100
|
|
cmsctl cms nodes get NODE_ID
|
|
cmsctl cms search --q "summer sale" --type page
|
|
cmsctl cms types
|
|
|
|
cmsctl cms nodes create \
|
|
--type page \
|
|
--data '{"title":"From the CLI"}' \
|
|
--tags published,homepage
|
|
|
|
cmsctl cms nodes update NODE_ID \
|
|
--data @replacement-data.json \
|
|
--tags published
|
|
```
|
|
|
|
`PUT /api/nodes/{id}` replaces the full `data` object. Use `cmsctl cms nodes
|
|
get` first and merge fields before updating, or use `--input` with a complete
|
|
`{"data":...,"tags":...}` request body. For a safe partial update, use the
|
|
native merge endpoint:
|
|
|
|
```bash
|
|
cmsctl cms nodes patch NODE_ID --data '{"data":{"title":"New"}}'
|
|
cmsctl cms nodes delete NODE_ID --yes
|
|
cmsctl cms nodes retype NODE_ID --type article
|
|
```
|
|
|
|
Graph and editorial operations are available directly:
|
|
|
|
```bash
|
|
cmsctl cms edges get NODE_ID
|
|
cmsctl cms edges create --from PAGE_ID --to BLOCK_ID --type child --sort 0
|
|
cmsctl cms edges reorder PAGE_ID --order EDGE_ID_1,EDGE_ID_2
|
|
cmsctl cms tree PAGE_ID --depth 3
|
|
cmsctl cms nav --data-type page
|
|
cmsctl cms graph --root PAGE_ID --budget 250 --edges child,ref
|
|
cmsctl cms publish PAGE_ID OTHER_PAGE_ID
|
|
cmsctl cms regenerate --type page
|
|
```
|
|
|
|
Schemas and templates can be inspected or edited in development mode. Writes
|
|
accept a file or `-` on stdin; destructive deletes require `--yes`:
|
|
|
|
```bash
|
|
cmsctl cms schemas list
|
|
cmsctl cms schemas get page > page.schema.json
|
|
cmsctl cms schemas put page page.schema.json
|
|
cmsctl cms templates get page.tmpl
|
|
cat page.tmpl | cmsctl cms templates put page -
|
|
cmsctl cms blueprints list
|
|
cmsctl cms blueprints create --blueprint landing --name "New landing"
|
|
```
|
|
|
|
The script command exposes the server-side CMS scripting API for atomic or
|
|
multi-step operations while retaining pipe-safe JSON output:
|
|
|
|
```bash
|
|
cmsctl cms script --script 'result(cms.listNodes({type:"todo",limit:0}))'
|
|
cat script-request.json | cmsctl cms script --input -
|
|
```
|
|
|
|
Bulk CMS import accepts the native `{nodes,edges}` request shape:
|
|
|
|
```bash
|
|
cmsctl cms import data/import.json
|
|
cat data/import.json | cmsctl cms import -
|
|
```
|
|
|
|
## Finder and inventory
|
|
|
|
Finder search emits the reader's JSONL response unchanged: product lines are
|
|
followed by the final search metadata line. This makes it easy to use with
|
|
`jq`, `awk`, or another streaming consumer.
|
|
|
|
```bash
|
|
cmsctl finder search --q drill --limit 20 --sort price_asc | jq -c .
|
|
cmsctl finder search --q window --filters '{"string":[{"id":"brand","value":["Dala"]}]}'
|
|
cmsctl finder get 861201
|
|
cmsctl finder get ABC-123 # SKU lookup is supported by finder
|
|
cmsctl finder config --stock in_stock
|
|
cmsctl finder facets --q drill
|
|
cmsctl finder facet-list
|
|
cmsctl finder values brand
|
|
cmsctl finder suggest --q dr
|
|
cmsctl finder popular
|
|
cmsctl finder related 861201
|
|
cmsctl finder compatible 861201 --limit 20
|
|
cmsctl finder compatible 861201 --cart-input cart-item-ids.json
|
|
cmsctl finder similar 861201
|
|
cmsctl finder relation-groups
|
|
cmsctl finder facet-groups
|
|
```
|
|
|
|
To materialize a bounded list of catalog items, pipe one numeric ID per line:
|
|
|
|
```bash
|
|
printf '861201\\n861202\\n' | cmsctl finder stream-items -
|
|
```
|
|
|
|
`finder search` also exposes the reader's important request controls:
|
|
`--filters`, `--stock`, `--sort`, `--mode`, `--disable-grouping`,
|
|
`--skip-facets`, and `--skip-tracking`. `--filters` is the JSON object sent as
|
|
the reader's `string`/`range` filter fields.
|
|
|
|
Writer administration is explicitly routed through the backoffice writeradmin
|
|
boundary (`<base-url>/catalog/admin`), never directly through `--finder-url`:
|
|
|
|
```bash
|
|
cmsctl finder admin settings get
|
|
cmsctl finder admin settings put settings.json
|
|
cmsctl finder admin facets list
|
|
cmsctl finder admin facets create facet.json
|
|
cmsctl finder admin facets update brand facet.json
|
|
cmsctl finder admin facets delete obsolete --yes
|
|
cmsctl finder admin update-by-filter update-request.json
|
|
cmsctl finder admin delete-by-filter filter.json --yes
|
|
```
|
|
|
|
The filter update body follows the writer contract:
|
|
`{"filter":{"string":[...] ,"range":[...]},"update":{...}}`. Filter
|
|
operations reject empty filters server-side; deletion also requires `--yes` in
|
|
the CLI.
|
|
|
|
|
|
Inventory/catalog imports accept either the writer's JSON array or one partial
|
|
item update per JSONL line. The CLI normalizes JSONL to the writer's batch
|
|
request before sending it to `POST /catalog/admin/items/batch`:
|
|
|
|
```bash
|
|
cat inventory.json | cmsctl finder import -
|
|
cat inventory.jsonl | cmsctl inventory import -
|
|
jq -c '.[]' products.json | cmsctl finder import -
|
|
```
|
|
|
|
Each finder import item follows the writer contract. For example:
|
|
|
|
```json
|
|
{"id":861201,"title":"New title","values":{"2":"Intel"}}
|
|
{"id":99000001,"buyable":true,"saleStatus":"ACT","values":{"4":50000}}
|
|
```
|
|
|
|
Updates are partial and merged by the finder writer; a `delete: true` item is a
|
|
catalog deletion. The persisted device token needs write authority for CMS and
|
|
finder mutations.
|