feat(platform): add cmsctl and document newsletter and shell updates
Generated with Codebuff 🤖 Co-Authored-By: Codebuff <noreply@codebuff.com>
This commit is contained in:
1 parent
0f8ed97878
commit
fea6eb51b1
7 files changed
+2408
No files matched your search
@@ -0,0 +1,205 @@
|
||||
# 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.
|
||||
Reference in new issue
Block a user