Documentation
¶
Index ¶
- Constants
- Variables
- func EncodeQueries(queries []string) string
- func NewHTTPClient(selfSigned bool) *http.Client
- func Paginate(list Lister, wrapper string, queries []string, pageSize int) ([]any, int64, error)
- func PaginateInto(list Lister, wrapper string, queries []string, pageSize int) ([]*jsonx.Object, int64, error)
- type APIError
- type Client
- func (c *Client) Call(method, path string, body any, out any) error
- func (c *Client) Clone() *Client
- func (c *Client) Download(path string) ([]byte, error)
- func (c *Client) List(path, wrapper string, queries []string) ([]*jsonx.Object, error)
- func (c *Client) SessionCookie() string
- func (c *Client) SetBearer(token string) *Client
- func (c *Client) SetCookie(cookie string) *Client
- func (c *Client) SetHeader(name, value string) *Client
- func (c *Client) SetJWT(jwt string) *Client
- func (c *Client) SetKey(key string) *Client
- func (c *Client) SetLocale(locale string) *Client
- func (c *Client) SetMode(mode string) *Client
- func (c *Client) SetOrganization(id string) *Client
- func (c *Client) SetProject(project string) *Client
- func (c *Client) SetSelfSigned(selfSigned bool) *Client
- func (c *Client) Upload(part UploadPart, out any) error
- func (c *Client) WithoutResponseFormat() *Client
- type FormField
- type Lister
- type Page
- type UploadPart
Constants ¶
const DefaultPageSize = 100
DefaultPageSize is the page size every list walk uses unless told otherwise.
const ResponseFormat = "1.8.1"
ResponseFormat pins the API response shape the CLI is written against.
Hard-coded: it tracks the API version the CLI was generated for, not the CLI's own version, so it must not be wired to sdk.version.
Variables ¶
var ExecutableName = "appwrite"
ExecutableName is the CLI's own name, for messages that name a command.
A package variable for the same reason RequestLog is one: internal/app owns the name, and app reaches this package through internal/sdk, so importing it would be a cycle. root.go sets it during start-up; the default is only what a test that never sets it reads.
var RequestLog func(format string, arguments ...any)
RequestLog receives one line per HTTP request when --verbose is on.
A package variable rather than a field on Client because clients are built in a dozen places and diagnostics should not have to be threaded through every one of them. Set once during start-up, before any request is made, and only read afterwards -- concurrent requests read it, none of them write it.
Functions ¶
func EncodeQueries ¶
EncodeQueries renders query strings as the API expects them.
`queries[0]=`, indexed -- NOT `queries[]=`. Both happen to work on the list endpoints, but the indexed form is what the request trace is pinned to, so the wire has to match too. Found by diffing traces on a command whose config output was already identical.
func NewHTTPClient ¶
NewHTTPClient returns the HTTP policy shared by the CLI's direct requests and its generated SDK-backed service commands.
A whole-request deadline makes a slow upload fail even while it is still making progress. The transport instead bounds the individual connection and response-header phases. Self-signed verification is configured before any caller wraps the transport, because the generated SDK cannot see through a recording RoundTripper to change it later.
func Paginate ¶
Paginate walks a list endpoint until every row has been read.
wrapper names the array in the response -- "functions", "rows" and so on.
Two conditions stop the walk, and both are needed. An empty page stops it because a server that reports a stale total would otherwise loop forever; reaching the total stops it because a full final page would otherwise cost one extra request.
func PaginateInto ¶
func PaginateInto(list Lister, wrapper string, queries []string, pageSize int) ([]*jsonx.Object, int64, error)
PaginateInto walks a list endpoint and returns the rows as objects.
Anything that is not an object is dropped rather than erroring: a list endpoint returns objects, and refusing to continue because one entry is malformed would fail a pull over a single bad row.
Types ¶
type APIError ¶
type APIError struct {
Status int
Code int `json:"code"`
Message string `json:"message"`
Type string `json:"type"`
OAuthError string `json:"error"`
OAuthDescription string `json:"error_description"`
}
APIError is a non-2xx response from the API. OAuthError and OAuthDescription cover RFC 6749 token endpoint failures, whose shape differs from the Appwrite API's code/message/type envelope.
type Client ¶
type Client struct {
Endpoint string
HTTP *http.Client
SDKVersion string
// contains filtered or unexported fields
}
Client is a thin HTTP client for the Appwrite API.
One client is shared across concurrent requests -- `push` runs deploy.UploadConcurrency chunk uploads through a single instance -- and every response can carry a Set-Cookie. The two cookie fields are the only mutable state, so one mutex covers them both.
func (*Client) Call ¶
Call performs a request and decodes the JSON response into out.
out may be nil for endpoints whose body is not needed. Numbers decode as json.Number so large integers survive.
func (*Client) Clone ¶
Clone returns a copy with its own header map, so that scoping one call to an organization does not scope the next unrelated one.
Field by field rather than `copied := *c`, which would copy the mutex -- vet rejects it, and it would snapshot the cookies without holding the lock.
func (*Client) Download ¶
Download fetches a path and returns the raw body.
Separate from Call because a deployment archive is not JSON, and decoding a gzip stream as JSON fails with a message about the first byte rather than about the archive.
func (*Client) List ¶
List walks a list endpoint through this client and returns its rows.
wrapper names the array in the response -- "functions", "rows" and so on. queries are the caller's own filters; the walk adds its own limit and offset per page. Page size is DefaultPageSize, which is the only size any caller has ever wanted.
func (*Client) SessionCookie ¶
SessionCookie is the console session cookie the server last set.
An accessor rather than a field because reading it unsynchronised while an upload is in flight is a data race.
func (*Client) SetJWT ¶
SetJWT authenticates with a JWT.
Deliberately unreachable for now: it completes the client setter surface, and the only caller will be the JwtManager that `run` still lacks.
func (*Client) SetOrganization ¶
SetOrganization names the organization for endpoints that take no ID in the path.
func (*Client) SetProject ¶
SetProject sets the project the request acts on.
func (*Client) SetSelfSigned ¶
SetSelfSigned accepts a self-signed TLS certificate.
Both the transport and the http.Client are copies, never the shared default and never mutated in place: Clone copies the *http.Client by pointer, so mutating either would disable certificate verification for every clone and sibling -- including calls to Appwrite Cloud this client never made.
func (*Client) Upload ¶
func (c *Client) Upload(part UploadPart, out any) error
Upload POSTs one multipart part and decodes the JSON response into out.
The body is assembled as three readers -- the form prefix, the file content, the closing boundary -- so its exact length is known without holding it. Content-Length matters here: without it Go falls back to chunked transfer-encoding, and the API sizes an upload from the header.
func (*Client) WithoutResponseFormat ¶
WithoutResponseFormat drops the x-appwrite-response-format header, which asks the API for that version's response shape: the console routes answer it with a legacy flat project instead of the `services`/`protocols`/`authMethods` arrays the config is built from. This reproduces what the console SDK sends.
type FormField ¶
FormField is one text field of a multipart upload.
Ordered rather than a map: the request body is what a recorded trace compares, and Go map iteration would reorder the parts on every run.
type Page ¶
type Page struct {
// Items are the rows under the wrapper key.
Items []any
// Total is the server's count of matching rows.
Total int64
}
Page is one response from a list endpoint.
type UploadPart ¶
type UploadPart struct {
Path string
Fields []FormField
// FileField is the form field the file is sent under, `code` for a
// deployment.
FileField string
FileName string
ContentType string
Content io.Reader
ContentLength int64
// Range is the content-range header. Empty for an upload that fits in one
// request, which the API answers without minting an upload id.
Range string
// UploadID pins this part to the upload the first chunk created.
UploadID string
}
UploadPart is one multipart request of a chunked upload.
Content is read as the request body rather than buffered, so the caller decides how much of a file is in memory at once -- for a deployment archive that is a section reader over the file and the answer is "none of it".