Skip to content

Custom post type routing, content files, media upload, raw api command, env credentials - #1

Open
sionsmith wants to merge 6 commits into
mainfrom
feat/content-primitives
Open

sionsmith wants to merge 6 commits into
mainfrom
feat/content-primitives

Conversation

@sionsmith

Copy link
Copy Markdown
Contributor

Generic primitives needed to drive real sites (first consumer: the oso.sh content pipeline).

  • post list|get|create|update|delete|search --type <slug>: resolves wp/v2/types/<slug> → rest_namespace/rest_base, so custom post types work (--rest-base skips the lookup). Fixes the previous --type that was emitted as --post-type and sent an ignored query param.
  • --context view|edit|embed on get/list; --content-file <path|->, --template, --featured-media on create/update; --slug filter on list.
  • --json stdin now passes unknown keys through (#[serde(flatten)] extra), plus template, featured_media, meta, acf.
  • media upload <file> [--title --alt-text --caption --description --post --mime-type] via multipart.
  • wpx api <METHOD> <path> [--data | --json] [--query k=v]... raw REST escape hatch (honours --dry-run).
  • Credentials from WPX_USERNAME + WPX_PASSWORD/WPX_APP_PASSWORD (with WPX_URL, no profile needed) for CI.
  • NO_COLOR / WPX_NO_PROMPT accept 1/0/yes/no.
  • crud.rs gains *_at helpers taking an explicit API path; docs and schema entries updated.

cargo fmt --check, cargo clippy --workspace -- -D warnings, cargo test --workspace (118 passed). Smoke-tested against oso.sh.

🤖 Generated with Claude Code

sionsmith and others added 6 commits October 8, 2026 11:53
… through post/page params

PostCreateParams and PageCreateParams previously had a fixed field set, so a
`--json` payload silently dropped `meta`, `acf`, `template`, `featured_media`
and custom taxonomy keys such as `blog_category`. Add those fields explicitly
plus a `#[serde(flatten)] extra` map so unknown keys reach WordPress verbatim.

The Post and Page response structs flatten unknown keys the same way, so
`--fields` masks can select anything WordPress returns (e.g. `blog_category`,
`acf`, `content.raw`) instead of losing it on deserialisation.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
- `request_raw(method, path, params, body)` performs any verb against any
  route under /wp-json/ with the usual auth, retry and error mapping; the
  method is validated against an allow-list.
- `upload_file(path, file_name, bytes, mime, fields)` builds the multipart
  form (file part + text fields) on top of the existing `post_multipart`.
- `patch()` complements get/post/put/delete.
- `mime_from_extension()` guesses MIME types for the WordPress default upload
  set without pulling in a mime crate.

Covered by wiremock integration tests in crates/wpx-api/tests.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
`SiteCredentials::from_env()` reads WPX_USERNAME plus WPX_PASSWORD (or the
WPX_APP_PASSWORD alias); `CredentialStore::resolve(site)` prefers those over
credentials.toml, following the documented env-over-files precedence. With
WPX_URL also set, no site profile or credentials file is needed, which is
what CI and agent sandboxes want.

build_client and `auth test` now use `resolve`, and their "site not found"
errors point at WPX_URL and the [sites.<name>] profile that is required.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…`wpx api`

Post commands can now target any post type exposed in REST. `--type <slug>`
resolves `GET wp/v2/types/{slug}` to `{rest_namespace}/{rest_base}` (core
types resolve without a lookup); `--rest-base` skips the lookup. This also
fixes `post list --type`, which used to send an ignored `?type=` query to
wp/v2/posts and returned the wrong collection. The flag was additionally being
emitted as `--post-type` because clap derives the long name from the field,
not the id; it is now `--type` as documented.

crud.rs gains `list_at / list_all_pages_at / get_at / create_at / update_at /
delete_at` taking an explicit collection path; the original helpers are thin
wrappers over `R::API_PATH`. `resolve_post_type_path` is shared by the CLI
and the fleet dispatcher.

New flags on post/page create and update: `--content-file <path|->`,
`--template`, `--featured-media`; `--context view|edit|embed` on get and list
(edit returns `content.raw`). `--json` payloads now keep unknown keys.

`wpx media upload <file> [--title --alt-text --caption --description --post
--mime-type]` posts a multipart form to wp/v2/media (dry-run aware).

`wpx api <METHOD> <path> [--data | --json] [--query k=v ...]` is the raw REST
escape hatch for routes without a typed command (plugin endpoints, revisions,
abilities). Non-GET requests honour `--dry-run`. Dispatch gains `["api"]` and
`["media", "upload"]` routes, and `["post", *]` routes honour `type` /
`rest_base`, stripping routing-only keys from the body.

Schema entries document the new inputs. Wiremock tests cover routing,
passthrough, dry-run and error mapping.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…d env credentials

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Env-backed boolean flags used clap's strict bool parser, so WPX_NO_PROMPT=1
failed with "invalid value '1'". Use BoolishValueParser for both.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant