client

package
v0.6.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 19, 2026 License: MIT Imports: 12 Imported by: 0

Documentation

Index

Constants

View Source
const (
	ExitOK          = 0
	ExitGeneric     = 1
	ExitUsage       = 2
	ExitAuth        = 3
	ExitNotFound    = 4
	ExitValidation  = 5
	ExitRateLimited = 6
	ExitServer      = 7
)

Documented CLI exit-code scheme (see docs/api-reference.md and the architecture). The cmd layer maps outcomes to these and os.Exit()s with them.

Variables

This section is empty.

Functions

func ExitCode

func ExitCode(err error) int

ExitCode maps a Client error to the documented exit-code scheme. A nil error is success (0); an *APIError maps by HTTP status (401→auth, 404→not-found, 429→rate-limited, other 4xx→validation, 5xx→server, 0→generic); any other error is generic (1). Wrapped *APIErrors are unwrapped via errors.As.

Types

type APIError

type APIError struct {
	StatusCode int
	Code       string
	Message    string
}

APIError is returned by Client methods when the request fails or the server returns an error envelope. StatusCode carries the HTTP status (0 for a transport-level failure); Code/Message come from the server's error object.

func (*APIError) Error

func (e *APIError) Error() string

Error implements the error interface.

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client is a typed HTTP client over the /api/v1 surface. It depends only on the JSON contract (stdlib) — it imports no server internals — which is what lets a future MCP server reuse it. Construct it with New.

func New

func New(baseURL, apiKey string) (*Client, error)

New builds a Client targeting baseURL authenticated with apiKey. The base URL is normalized (trailing slash trimmed) and must be an http(s) scheme + host with no userinfo and no path (the client appends /api/v1/...); rejecting a path avoids a silent double-prefix when callers proxy under a path. The returned Client follows redirects but strips the API key on cross-host hops. A default 30s per-request timeout is applied so a hung server cannot block the CLI indefinitely.

func (*Client) CreateComment added in v0.3.0

func (c *Client) CreateComment(
	ctx context.Context,
	contentID int,
	req CreateCommentRequest,
) (json.RawMessage, json.RawMessage, error)

CreateComment POSTs a comment to /api/v1/content/{id}/comments and returns the decoded data and meta payloads, or an *APIError on failure.

func (*Client) CreateContent

func (c *Client) CreateContent(
	ctx context.Context,
	req CreateContentRequest,
) (json.RawMessage, json.RawMessage, error)

CreateContent POSTs a content-create request to /api/v1/content and returns the decoded data and meta payloads, or an *APIError on failure.

func (*Client) DeleteComment added in v0.3.0

func (c *Client) DeleteComment(
	ctx context.Context,
	contentID int,
	commentID int,
) (json.RawMessage, json.RawMessage, error)

DeleteComment sends DELETE /api/v1/content/{id}/comments/{commentId}. A 204 No Content success returns (nil, nil, nil); a 404 or other 4xx/5xx returns an *APIError. An admin key may delete any comment; a non-admin key only its own (the server returns 404 for a comment the caller does not own, no disclosure).

func (*Client) DeleteContent

func (c *Client) DeleteContent(
	ctx context.Context,
	id int,
) (json.RawMessage, json.RawMessage, error)

DeleteContent sends DELETE /api/v1/content/{id}. A 204 No Content success returns (nil, nil, nil); a 404 or other 4xx/5xx returns an *APIError.

func (*Client) GetContent

func (c *Client) GetContent(
	ctx context.Context,
	id int,
) (json.RawMessage, json.RawMessage, error)

GetContent sends GET /api/v1/content/{id} and returns the decoded data and meta payloads, or an *APIError on failure.

func (*Client) GetMedia

func (c *Client) GetMedia(
	ctx context.Context,
	id int,
) (json.RawMessage, json.RawMessage, error)

GetMedia sends GET /api/v1/media/{id} and returns the decoded data and meta payloads, or an *APIError on failure.

func (*Client) ListComments added in v0.3.0

func (c *Client) ListComments(
	ctx context.Context,
	contentID int,
) (json.RawMessage, json.RawMessage, error)

ListComments sends GET /api/v1/content/{id}/comments and returns the decoded data (a bare array of comment projections) and meta, or an *APIError on failure.

func (*Client) ListContent

func (c *Client) ListContent(
	ctx context.Context,
	limit int,
	cursor string,
	filters ListContentFilters,
) (json.RawMessage, json.RawMessage, error)

ListContent sends GET /api/v1/content?limit=&cursor=&tag=&language=&status=&post_type=&author=&search= and returns the decoded data (a bare array of content projections) and meta (with pagination), or an *APIError on failure. A limit of 0 (or negative) is passed as "no limit" (the server uses its default); an empty cursor is passed as "no cursor" (the first page). Each non-empty filter field emits its query key; an empty field is omitted entirely so the wire stays minimal. Tags is expanded into repeated ?tag= keys (one per tag) so the server can AND-of-tags.

func (*Client) ListMedia

func (c *Client) ListMedia(
	ctx context.Context,
	limit int,
	cursor string,
) (json.RawMessage, json.RawMessage, error)

ListMedia sends GET /api/v1/media?limit=&cursor= and returns the decoded data (a bare array of media projections) and meta (with pagination), or an *APIError on failure. A limit of 0 (or negative) is passed as "no limit" (the server uses its default); an empty cursor is passed as "no cursor" (the first page).

func (*Client) PublishContent

func (c *Client) PublishContent(
	ctx context.Context,
	id int,
) (json.RawMessage, json.RawMessage, error)

PublishContent sends POST /api/v1/content/{id}/publish with an empty body and returns the decoded data and meta payloads, or an *APIError on failure. The server endpoint is idempotent: publishing an already-published post returns 200 with the current projection. Ownership is enforced server-side; a non-admin non-owner call returns 404 (not 403, no disclosure).

func (*Client) SetSystemFields added in v0.2.0

func (c *Client) SetSystemFields(
	ctx context.Context,
	id int,
	systemFields map[string]any,
) (json.RawMessage, json.RawMessage, error)

SetSystemFields sends PUT /api/v1/content/{id}/system-fields with the given system field key/value pairs and returns the decoded data and meta payloads, or an *APIError on failure. System fields are admin-managed metadata (e.g. editorial_status, internal_notes), so the server returns 403 FORBIDDEN unless the API key belongs to an Admin; an unknown key returns ErrUnknownSystemFieldKey and a value that fails the field schema returns ErrSystemFieldValidation, both surfaced as a 400 VALIDATION_ERROR.

func (*Client) UnpublishContent

func (c *Client) UnpublishContent(
	ctx context.Context,
	id int,
) (json.RawMessage, json.RawMessage, error)

UnpublishContent sends POST /api/v1/content/{id}/unpublish with an empty body and returns the decoded data and meta payloads, or an *APIError on failure. The server endpoint is idempotent: unpublishing an already-draft post returns 200 with the current projection. Same ownership contract as PublishContent.

func (*Client) UpdateCommentStatus added in v0.3.0

func (c *Client) UpdateCommentStatus(
	ctx context.Context,
	contentID int,
	commentID int,
	status string,
) (json.RawMessage, json.RawMessage, error)

UpdateCommentStatus sends PUT /api/v1/content/{id}/comments/{commentId}/status with the given status (approved/rejected/spam) and returns the decoded data and meta payloads, or an *APIError on failure. Admin only: the server returns 403 FORBIDDEN to a non-admin key.

func (*Client) UpdateContent

func (c *Client) UpdateContent(
	ctx context.Context,
	id int,
	req UpdateContentRequest,
) (json.RawMessage, json.RawMessage, error)

UpdateContent sends PUT /api/v1/content/{id} with the given request body and returns the decoded data and meta payloads, or an *APIError on failure. The request body is the same shape as CreateContent. The server's update handler preserves the server-managed fields (SEO metadata — metaDescription / ogTitle / ogDescription, allowComments, translationGroupId) from the existing item, so a partial update that omits them is safe; postType / tags / language are now settable and forwarded as-given (the server validates them).

func (*Client) UploadMedia

func (c *Client) UploadMedia(
	ctx context.Context,
	req UploadMediaRequest,
) (json.RawMessage, json.RawMessage, error)

UploadMedia sends POST /api/v1/media as multipart/form-data with a `file` part and an optional `metadata` JSON part, then returns the decoded data and meta payloads (the server returns 200 with the media projection in the data envelope) or an *APIError on failure.

The multipart body is buffered in memory; the server enforces its own size limit at r.ParseMultipartForm. The 204/304+envelope defenses from doRequest apply unchanged.

type CreateCommentRequest added in v0.3.0

type CreateCommentRequest struct {
	Comment string `json:"comment"`
}

CreateCommentRequest is the agent comment-create payload. It mirrors the {data, error, meta} contract documented in docs/api-reference.md — the client hard-codes it (it cannot import the server's DTO types).

type CreateContentRequest

type CreateContentRequest struct {
	Title              string         `json:"title"`
	Body               string         `json:"body"`
	Format             string         `json:"format,omitempty"`
	PostType           string         `json:"postType,omitempty"`
	Tags               []string       `json:"tags,omitempty"`
	Language           string         `json:"language,omitempty"`
	IsPublished        bool           `json:"isPublished,omitempty"`
	CustomFields       map[string]any `json:"customFields,omitempty"`
	TranslationGroupID *int           `json:"translationGroupId,omitempty"`
}

CreateContentRequest is the agent content-create payload. It mirrors the {data, error, meta} contract documented in docs/api-reference.md — the client hard-codes it (it cannot import the server's DTO types).

All metadata fields (PostType, Tags, Language) use `omitempty` so an unset value is identical on the wire to a default-zero request. Tags must already be normalized by the caller (the CLI's normalizeTags helper trims, drops empties, and dedupes); the server re-validates via contentdomain.ValidateTags. Language is forwarded as-given — the server is the single source of truth for the configured-languages list (it returns ErrInvalidLanguage for an unknown code, mapped to 400 VALIDATION_ERROR by the CLI's exit code map).

type ListContentFilters

type ListContentFilters struct {
	Tags     []string
	Language string
	Status   string
	PostType string
	Author   string
	Search   string
}

ListContentFilters is the cmd-layer projection of contentdomain.ContentFilters for the agent List endpoint. The CLI re-declares the shape (it cannot import server-internal types) so the wire contract is the source of truth, and only the fields used by the agent v1 surface are exposed here. Tags is intentionally a slice — the wire format uses repeated ?tag= keys (one per tag, AND-of-tags on the server). An empty / zero struct produces a no-filter call (server returns the unfiltered list).

type UpdateContentRequest

type UpdateContentRequest struct {
	Title        string         `json:"title"`
	Body         string         `json:"body"`
	Format       string         `json:"format,omitempty"`
	PostType     string         `json:"postType,omitempty"`
	Tags         []string       `json:"tags,omitempty"`
	Language     string         `json:"language,omitempty"`
	IsPublished  bool           `json:"isPublished,omitempty"`
	CustomFields map[string]any `json:"customFields,omitempty"`
}

UpdateContentRequest is the agent content-update payload. It carries the same fields as CreateContentRequest because the server's PUT /api/v1/content/{id} accepts the same ContentRequest shape. The server preserves the server-managed fields (SEO metadata — metaDescription / ogTitle / ogDescription, allowComments, translationGroupId) from the existing item; the client does not surface a flag for translationGroupId on update (the server ignores it). CustomFields may be set: when non-nil it replaces the item's custom fields (preserving plugin-managed system fields); when nil the existing custom fields are preserved. The client cannot import the server's DTO types so the subset is re-declared here.

type UploadMediaRequest

type UploadMediaRequest struct {
	File     io.Reader
	Filename string
	Metadata map[string]any
}

UploadMediaRequest is the multipart payload sent to POST /api/v1/media. It is built in memory by UploadMedia — callers supply the file reader + filename and an optional metadata map (the server reads `altText` today; the map values are passed through as typed JSON so non-string values such as numbers or booleans are accepted, even though the server currently persists only `altText`). The client validates that File is non-nil and Filename is non-empty so a bad call site fails fast with a clear error instead of a runtime panic.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL