Documentation
¶
Overview ¶
Package zotero is zotgo's client for a running Zotero 7+ desktop app.
It speaks only Zotero's own HTTP contracts — today the Local API (/api/*), which is read-only — and never opens zotero.sqlite. The package depends on the standard library alone.
This is an internal package, not a published SDK: it cannot be imported from outside this module, and its API is free to change with zotgo's needs.
Index ¶
- Constants
- Variables
- func ExportFormats() []string
- func ManagedAttachmentLinkMode(linkMode string) (bool, error)
- func RequireItemType(raw json.RawMessage, want string) error
- type Annotation
- type Attachment
- type AttachmentEnclosure
- type AttachmentUploadAuthorization
- type AttachmentUploadMetadata
- type Authenticator
- type Capability
- type CapabilityStatus
- type ChildItemsOptions
- type Client
- func (c *Client) AllCollections(ctx context.Context, library LibraryRef, opts CollectionsOptions) ([]Envelope, error)
- func (c *Client) AllItems(ctx context.Context, library LibraryRef, opts ItemsOptions) ([]Envelope, error)
- func (c *Client) AllRawAnnotations(ctx context.Context, library LibraryRef, attachmentKey string) ([]json.RawMessage, error)
- func (c *Client) AllRawChildItems(ctx context.Context, library LibraryRef, parentKey string, ...) ([]json.RawMessage, error)
- func (c *Client) Attachment(ctx context.Context, library LibraryRef, key string) (Attachment, error)
- func (c *Client) Authorize(ctx context.Context, appName string) (remember bool, err error)
- func (c *Client) AuthorizeAttachmentUpload(ctx context.Context, library LibraryRef, attachmentKey string, ...) (AttachmentUploadAuthorization, error)
- func (c *Client) BaseURL() string
- func (c *Client) CheckHealth(ctx context.Context) Health
- func (c *Client) Collection(ctx context.Context, library LibraryRef, key string) (Envelope, error)
- func (c *Client) Collections(ctx context.Context, library LibraryRef, opts CollectionsOptions) ([]Envelope, Page, error)
- func (c *Client) CreateCollections(ctx context.Context, op Operation, lib LibraryRef, cols []json.RawMessage) (WriteResult, error)
- func (c *Client) CreateItems(ctx context.Context, op Operation, lib LibraryRef, items []json.RawMessage) (WriteResult, error)
- func (c *Client) CreateItemsReturningKeys(ctx context.Context, op Operation, lib LibraryRef, items []json.RawMessage) (KeyWriteResult, error)
- func (c *Client) DeleteCollections(ctx context.Context, op Operation, lib LibraryRef, keys []string, ...) error
- func (c *Client) DeleteItems(ctx context.Context, op Operation, lib LibraryRef, keys []string, ...) error
- func (c *Client) DeleteTags(ctx context.Context, op Operation, lib LibraryRef, names []string, ...) error
- func (c *Client) Export(ctx context.Context, library LibraryRef, opts ItemsOptions, format string) ([]byte, error)
- func (c *Client) Groups(ctx context.Context) ([]Group, error)
- func (c *Client) HasLocalKey() bool
- func (c *Client) Item(ctx context.Context, library LibraryRef, key string) (Envelope, error)
- func (c *Client) ItemChildren(ctx context.Context, library LibraryRef, key string) ([]Envelope, Page, error)
- func (c *Client) ItemTemplate(ctx context.Context, itemType string) (json.RawMessage, error)
- func (c *Client) Items(ctx context.Context, library LibraryRef, opts ItemsOptions) ([]Envelope, Page, error)
- func (c *Client) IterItems(ctx context.Context, library LibraryRef, opts ItemsOptions, ...) error
- func (c *Client) LibraryFileAccess(ctx context.Context) ([]LibraryFiles, error)
- func (c *Client) LibraryVersion(ctx context.Context, lib LibraryRef) (int, error)
- func (c *Client) LocalKey() string
- func (c *Client) Note(ctx context.Context, library LibraryRef, key string) (Note, error)
- func (c *Client) PatchCollection(ctx context.Context, op Operation, lib LibraryRef, key string, ...) error
- func (c *Client) PatchItem(ctx context.Context, op Operation, lib LibraryRef, key string, ...) error
- func (c *Client) Profile() Profile
- func (c *Client) RawChildItems(ctx context.Context, library LibraryRef, parentKey string, ...) ([]json.RawMessage, Page, error)
- func (c *Client) RawItem(ctx context.Context, library LibraryRef, key string) (json.RawMessage, error)
- func (c *Client) RawItemWithChildren(ctx context.Context, library LibraryRef, key string) (json.RawMessage, []json.RawMessage, error)
- func (c *Client) RegisterAttachmentUpload(ctx context.Context, library LibraryRef, attachmentKey, uploadKey string) error
- func (c *Client) ReplaceItem(ctx context.Context, op Operation, lib LibraryRef, key string, ...) error
- func (c *Client) RequireWriteCapability(ctx context.Context) error
- func (c *Client) ResolveLibrary(ctx context.Context, selector string) (LibraryRef, error)
- func (c *Client) ServerID() string
- func (c *Client) SetLocalKey(key string)
- func (c *Client) SetWriteAuthorizer(a WriteAuthorizer)
- func (c *Client) Stats(ctx context.Context, library LibraryRef) (Stats, error)
- func (c *Client) UploadAuthorizedAttachment(ctx context.Context, authorization AttachmentUploadAuthorization, ...) error
- func (c *Client) WebKey(ctx context.Context) (WebKey, error)
- type CollectionData
- type CollectionPath
- type CollectionPathSegment
- type CollectionsOptions
- type Creator
- type EndpointKind
- type Envelope
- func (e Envelope) AttachmentData() (Attachment, error)
- func (e Envelope) CollectionData() (CollectionData, error)
- func (e Envelope) CreatorSummary() string
- func (e Envelope) ItemData() (ItemData, error)
- func (e Envelope) ItemType() string
- func (e Envelope) NoteData() (Note, error)
- func (e Envelope) NumChildren() int
- func (e Envelope) ParsedDate() string
- func (e Envelope) Title() string
- func (e *Envelope) UnmarshalJSON(data []byte) error
- type Group
- type GroupData
- type GroupMeta
- type Health
- type ItemData
- type ItemIdentity
- type ItemsOptions
- type KeyWriteResult
- type Library
- type LibraryFiles
- type LibraryRef
- type Link
- type Note
- type Operation
- type Option
- type Page
- type Profile
- type Relation
- type Stats
- type StatusError
- type Tag
- type WebAccess
- type WebGroupAccess
- type WebKey
- type WebUserAccess
- type WriteAuthorizer
- type WriteFailure
- type WriteResult
Constants ¶
const ( LibraryKindUser = "user" LibraryKindGroup = "group" )
const AuthorizeTimeout = 2 * time.Minute
AuthorizeTimeout bounds how long Authorize waits for the user to answer Zotero's approval modal. It is far longer than a normal request because a person has to click Allow or Deny.
const DefaultBaseURL = "http://localhost:23119"
DefaultBaseURL is Zotero's default local HTTP server address.
const DefaultTimeout = 5 * time.Second
DefaultTimeout bounds a single Local API round-trip, body included.
const DefaultWebBaseURL = "https://api.zotero.org"
DefaultWebBaseURL is the hosted Web API's address.
const DefaultWebTimeout = 30 * time.Second
DefaultWebTimeout bounds a single Web API round-trip. It is looser than the local default because the request crosses the public internet rather than a loopback socket.
const LocalWriteUnsupportedReason = "this Zotero build has no local write API (added upstream in zotero/zotero#5015; update Zotero once a release ships it)"
LocalWriteUnsupportedReason explains a local endpoint whose Zotero build predates the write API. It is shared by doctor's capability report and the write commands' pre-flight so the two never drift.
const ( // MaxAttachmentFileSize is zotgo's explicit, conservative limit while // Zotero's Local API receiver buffers an upload before staging it to disk. MaxAttachmentFileSize int64 = 128 * 1024 * 1024 )
const MaxDeleteObjects = 50
MaxDeleteObjects is the most keys accepted in one multi-delete (upstream MAX_DELETE_OBJECTS).
const MaxWriteObjects = 50
MaxWriteObjects is the most objects the local write API accepts in one batch (MAX_WRITE_OBJECTS upstream).
Variables ¶
var ( // ErrZoteroDown means the endpoint refused a connection: nothing is // listening, so Zotero is not running. ErrZoteroDown = errors.New("zotero is not running") // ErrTransport means the request failed after a connection was established. // Zotero may well be running; the exchange itself broke. ErrTransport = errors.New("zotero request failed") // ErrBadPagination means Zotero advertised a rel="next" cursor that cannot // be followed: no start offset, an unparseable one, or one that does not // advance. Following it would loop forever. ErrBadPagination = errors.New("zotero returned an unusable pagination cursor") // ErrUnsupportedFormat means the requested export format is not one of the // Zotero translators zotgo knows how to reassemble across pages. ErrUnsupportedFormat = errors.New("unsupported export format") // ErrUnmergeableExport means the result spans several pages in a format // whose pages cannot be joined into one valid document. ErrUnmergeableExport = errors.New("export spans pages that cannot be merged") // ErrLocalAPIDisabled means Zotero is running, but the Local API pref is off. ErrLocalAPIDisabled = errors.New("zotero local api is disabled") // ErrNotFound means Zotero returned 404 for a requested object. ErrNotFound = errors.New("zotero object not found") // ErrLibraryNotFound means a library selector did not match My Library or a group. ErrLibraryNotFound = errors.New("zotero library not found") // ErrAmbiguousLibrary means a library selector matched more than one group name. ErrAmbiguousLibrary = errors.New("zotero library selector is ambiguous") // ErrInvalidAPIKey means the Web API rejected the API key, or it resolved to // no user: it is missing, revoked, or wrong. ErrInvalidAPIKey = errors.New("zotero web api key is invalid") // ErrWriteUnsupported means the local Zotero build has no write API, so a // write cannot succeed. Its message is the actionable reason. ErrWriteUnsupported = errors.New(LocalWriteUnsupportedReason) // ErrAuthorizeDenied means the user declined the local write authorization // prompt in Zotero. ErrAuthorizeDenied = errors.New("zotero write authorization denied") // ErrWriteNotAuthorized means no WriteAuthorizer permitted the write: none was // installed (deny-by-default) or the installed one refused without a more // specific reason. It is distinct from ErrWriteUnauthorized, which is Zotero's // own 401 for a bad key. ErrWriteNotAuthorized = errors.New("write not authorized") // consumed local API key (HTTP 401): re-authorize. ErrWriteUnauthorized = errors.New("zotero local write not authorized") // ErrPreconditionRequired means a required write precondition header was // absent (HTTP 428): the Zotero-Server-ID or If-Unmodified-Since-Version. ErrPreconditionRequired = errors.New("zotero write precondition required") // ErrPreconditionFailed means a write precondition did not hold (HTTP 412): // the Zotero-Server-ID no longer matches, or the library changed since the // version the write was based on. ErrPreconditionFailed = errors.New("zotero write precondition failed") // ErrWriteOutcomeUnknown means Zotero accepted a mutating request but its // successful response could not be decoded, so the created object's key is // unavailable and retrying might duplicate data. ErrWriteOutcomeUnknown = errors.New("zotero write outcome is unknown") )
Functions ¶
func ExportFormats ¶ added in v0.3.0
func ExportFormats() []string
ExportFormats lists the server-side translator names Export accepts, sorted.
func ManagedAttachmentLinkMode ¶ added in v0.9.0
ManagedAttachmentLinkMode reports whether linkMode identifies storage owned by Zotero. Unknown modes fail closed so callers do not treat future managed modes as ordinary linked attachments.
func RequireItemType ¶ added in v0.9.0
func RequireItemType(raw json.RawMessage, want string) error
RequireItemType checks one raw item's family without decoding any other fields.
Types ¶
type Annotation ¶ added in v0.9.0
type Annotation struct {
Key string
AttachmentKey string
Type string
PageLabel string
Color string
SortIndex string
HasText bool
HasComment bool
}
Annotation is compact metadata for one attachment annotation. Text, comments, position data, and image bytes remain outside this listing model.
func DecodeAnnotation ¶ added in v0.9.0
func DecodeAnnotation(raw json.RawMessage) (Annotation, error)
DecodeAnnotation validates and decodes compact annotation metadata from one complete Zotero item envelope.
func DecodeAnnotations ¶ added in v0.9.0
func DecodeAnnotations(rawItems []json.RawMessage, attachmentKey string) ([]Annotation, error)
DecodeAnnotations validates one attachment's annotations and returns them in document order: sort index first, key as a deterministic tie-breaker, and missing sort indexes last.
type Attachment ¶ added in v0.9.0
type Attachment struct {
Key string
ParentKey string
Title string
LinkMode string
ContentType string
Charset string
Filename string
URL string
AccessDate string
DateAdded string
DateModified string
Tags []Tag
MD5 *string
MTime *int64
Enclosure *AttachmentEnclosure
}
Attachment is the metadata Zotero exposes for one attachment item. It contains no filesystem-derived state.
func DecodeAttachment ¶ added in v0.9.0
func DecodeAttachment(raw json.RawMessage) (Attachment, error)
DecodeAttachment decodes the bounded attachment fields from a raw item envelope. Unrelated link objects remain outside the typed contract.
type AttachmentEnclosure ¶ added in v0.9.0
type AttachmentEnclosure struct {
Href string `json:"href"`
Type string `json:"type"`
Title string `json:"title"`
Length *int64 `json:"length"`
}
AttachmentEnclosure is the location and optional size metadata Zotero advertises for a stored attachment.
type AttachmentUploadAuthorization ¶ added in v0.9.0
AttachmentUploadAuthorization is Zotero's response to the file authorize phase.
type AttachmentUploadMetadata ¶ added in v0.9.0
type AttachmentUploadMetadata struct {
MD5 string
Filename string
Size int64
MTime int64
ContentType string
}
AttachmentUploadMetadata describes the immutable file staged for upload.
type Authenticator ¶ added in v0.5.0
type Authenticator interface {
// contains filtered or unexported methods
}
An Authenticator applies an endpoint's credentials to an outbound request.
It is a Client collaborator rather than part of the Profile so that the credential never rides along with the endpoint's printable identity. The local endpoint needs no credential; the Web API needs an API key.
The method is unexported: the two endpoints zotgo speaks to are the only authentication strategies there are, so there is nothing for an outside implementation to add.
type Capability ¶ added in v0.3.0
type Capability string
Capability is something an endpoint can do. It describes the *endpoint*, not what zotgo has implemented against it: doctor answers "what does this Zotero allow?", and a capability may be available before a command uses it.
const ( // CapabilityRead is reading items, collections, and tags. CapabilityRead Capability = "read" // CapabilityWrite is creating, updating, or deleting objects through the // official API write contract. CapabilityWrite Capability = "write" // CapabilityConnectorIngest is app-mediated ingestion over /connector/*: // PDF recognition, file import, snapshots. CapabilityConnectorIngest Capability = "connector-ingest" // CapabilityLocalFileAccess is resolving an attachment to a local file path. CapabilityLocalFileAccess Capability = "local-file-access" )
type CapabilityStatus ¶ added in v0.3.0
type CapabilityStatus struct {
Name Capability
Supported bool
// Reason explains an unsupported capability, in terms the user can act on
// or at least understand. Empty when Supported.
Reason string
}
CapabilityStatus reports whether one capability is available, and why not when it is missing. A missing capability without a reason is a bug: the user is left with nothing to act on.
type ChildItemsOptions ¶ added in v0.9.0
ChildItemsOptions controls requests for the children of an item.
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client talks to a running Zotero over its Local API and Connector API, or to the hosted Web API — which of the two is fixed by its Profile at construction.
A Client is safe for concurrent use. It performs no I/O until a method is called; construction never fails.
func New ¶
New returns a Client for a running local Zotero at baseURL, or DefaultBaseURL when baseURL is empty. The local endpoint needs no credential. Options are applied in order.
func NewWeb ¶ added in v0.5.0
NewWeb returns a Client for the hosted Web API at baseURL, or DefaultWebBaseURL when baseURL is empty, authenticated with apiKey. Options are applied in order.
func (*Client) AllCollections ¶
func (c *Client) AllCollections(ctx context.Context, library LibraryRef, opts CollectionsOptions) ([]Envelope, error)
AllCollections follows Link rel="next" and returns every collection.
func (*Client) AllItems ¶
func (c *Client) AllItems(ctx context.Context, library LibraryRef, opts ItemsOptions) ([]Envelope, error)
AllItems follows Link rel="next" and returns the full result set.
func (*Client) AllRawAnnotations ¶ added in v0.9.0
func (c *Client) AllRawAnnotations(ctx context.Context, library LibraryRef, attachmentKey string) ([]json.RawMessage, error)
AllRawAnnotations reads every direct annotation child of one attachment. It validates that the parent is an attachment and honors the parent response's backoff before requesting children, then returns complete annotation envelopes in server order — or no partial result if any page fails. It encapsulates the parent-fetch + validate + backoff + child-fetch dance behind one call, matching how Note/Attachment/RawItemWithChildren expose their reads.
func (*Client) AllRawChildItems ¶ added in v0.9.0
func (c *Client) AllRawChildItems(ctx context.Context, library LibraryRef, parentKey string, opts ChildItemsOptions) ([]json.RawMessage, error)
AllRawChildItems follows Link rel="next" and returns every complete child item envelope in server order. It returns no partial result if any page fails.
func (*Client) Attachment ¶ added in v0.9.0
func (c *Client) Attachment(ctx context.Context, library LibraryRef, key string) (Attachment, error)
Attachment reads and decodes one attachment's bounded metadata.
func (*Client) Authorize ¶ added in v0.6.0
Authorize obtains a local API key for writes by asking Zotero to prompt the user; appName is shown in the modal. On approval it stores the key for subsequent writes and reports whether Zotero will remember it (persistent) or granted single-use access. Only the local endpoint supports it.
It returns ErrAuthorizeDenied if the user declines. The key is never logged.
func (*Client) AuthorizeAttachmentUpload ¶ added in v0.9.0
func (c *Client) AuthorizeAttachmentUpload(ctx context.Context, library LibraryRef, attachmentKey string, metadata AttachmentUploadMetadata) (AttachmentUploadAuthorization, error)
AuthorizeAttachmentUpload requests a new full-file upload or learns that the attachment already has matching bytes.
func (*Client) CheckHealth ¶
CheckHealth probes the active endpoint and returns a Health snapshot. It never returns an error: an unreachable or misconfigured endpoint is a normal, renderable result, not a failure of the probe.
func (*Client) Collection ¶ added in v0.6.0
Collection reads one collection by key.
func (*Client) Collections ¶
func (c *Client) Collections(ctx context.Context, library LibraryRef, opts CollectionsOptions) ([]Envelope, Page, error)
Collections reads a single page of collections.
func (*Client) CreateCollections ¶ added in v0.6.0
func (c *Client) CreateCollections(ctx context.Context, op Operation, lib LibraryRef, cols []json.RawMessage) (WriteResult, error)
CreateCollections creates collections ({name, parentCollection}) in one batch.
func (*Client) CreateItems ¶ added in v0.6.0
func (c *Client) CreateItems(ctx context.Context, op Operation, lib LibraryRef, items []json.RawMessage) (WriteResult, error)
CreateItems creates items from their JSON representations (itemType plus fields) in one batch write.
func (*Client) CreateItemsReturningKeys ¶ added in v0.9.0
func (c *Client) CreateItemsReturningKeys(ctx context.Context, op Operation, lib LibraryRef, items []json.RawMessage) (KeyWriteResult, error)
CreateItemsReturningKeys creates items while decoding only generated keys.
func (*Client) DeleteCollections ¶ added in v0.6.0
func (c *Client) DeleteCollections(ctx context.Context, op Operation, lib LibraryRef, keys []string, ifUnmodifiedSince int) error
DeleteCollections removes collections by key (collectionKey=…). Deleting a collection does not delete its items.
func (*Client) DeleteItems ¶ added in v0.6.0
func (c *Client) DeleteItems(ctx context.Context, op Operation, lib LibraryRef, keys []string, ifUnmodifiedSince int) error
DeleteItems removes items by key in one request (itemKey=…).
func (*Client) DeleteTags ¶ added in v0.6.0
func (c *Client) DeleteTags(ctx context.Context, op Operation, lib LibraryRef, names []string, ifUnmodifiedSince int) error
DeleteTags removes tags from the whole library by name (tag=a||b||…), stripping each from every item. Names are joined with "||" as the API expects.
func (*Client) Export ¶ added in v0.3.0
func (c *Client) Export(ctx context.Context, library LibraryRef, opts ItemsOptions, format string) ([]byte, error)
Export returns the items matching opts rendered by one of Zotero's own translators (format=…), reassembled across pages.
Zotero does the formatting; zotgo only rejoins what pagination split. A format whose pages cannot be rejoined into a valid document yields ErrUnmergeableExport rather than corrupt output.
func (*Client) Groups ¶
Groups lists the groups the endpoint's own user can reach. On the Web API the route carries the key owner's real id; locally it is the "0" sentinel.
func (*Client) HasLocalKey ¶ added in v0.6.0
HasLocalKey reports whether the client holds a local API key for writes.
func (*Client) ItemChildren ¶
func (c *Client) ItemChildren(ctx context.Context, library LibraryRef, key string) ([]Envelope, Page, error)
ItemChildren reads one page of attachments and notes under a parent item.
func (*Client) ItemTemplate ¶ added in v0.6.0
ItemTemplate returns a blank item of itemType, assembled from the Local API's itemTypeFields and itemTypeCreatorTypes endpoints — the Local API has no /items/new template route. Fields appear in Zotero's order with itemType first, plus one empty creator of the primary type and empty tags/collections/ relations, ready to fill in and pass to CreateItems.
Special item types (note, attachment) carry their content outside these fields, so their template will be sparse. An unknown type yields a clear error.
func (*Client) Items ¶
func (c *Client) Items(ctx context.Context, library LibraryRef, opts ItemsOptions) ([]Envelope, Page, error)
Items reads a single page of items.
func (*Client) IterItems ¶ added in v0.8.0
func (c *Client) IterItems(ctx context.Context, library LibraryRef, opts ItemsOptions, yield func([]Envelope) error) error
IterItems fetches items one page at a time and passes each page to yield in order, so a caller can process a very large library without ever holding all of it in memory. Pagination, the start cursor, and Web API backoff are handled exactly as AllItems. If yield returns an error, iteration stops and that error is returned unchanged; a nil error runs to the last page.
func (*Client) LibraryFileAccess ¶ added in v0.9.0
func (c *Client) LibraryFileAccess(ctx context.Context) ([]LibraryFiles, error)
LibraryFileAccess lists, per library the running Zotero can currently file into, whether that library accepts attachment files. It is pure diagnosis: one POST /connector/getSelectedCollection — the same Connector surface doctor already pings for liveness — with no ingestion semantics, so it does not touch the "connector is not a write backend" boundary. Local endpoint only.
func (*Client) LibraryVersion ¶ added in v0.6.0
LibraryVersion returns the library's current clientVersion, read from the Last-Modified-Version header of a cheap list request. Bulk writes and deletes use it as If-Unmodified-Since-Version. Single-object PATCH requests must use that object's version instead.
func (*Client) LocalKey ¶ added in v0.6.0
LocalKey returns the client's local API key, for a caller that wants to persist a freshly authorized one. Empty when none is held.
func (*Client) Note ¶ added in v0.9.0
Note reads and decodes one note's bounded metadata and rich-text HTML.
func (*Client) PatchCollection ¶ added in v0.6.0
func (c *Client) PatchCollection(ctx context.Context, op Operation, lib LibraryRef, key string, patch json.RawMessage, ifUnmodifiedSince int) error
PatchCollection applies a partial update to one collection. It backs collection.rename ({"name":…}) and collection.move ({"parentCollection":…}), so the caller names the operation.
func (*Client) PatchItem ¶ added in v0.6.0
func (c *Client) PatchItem(ctx context.Context, op Operation, lib LibraryRef, key string, patch json.RawMessage, ifUnmodifiedSince int) error
PatchItem applies a partial update (a JSON object of fields to change) to one item. It backs item.patch as well as tag.add/tag.remove, which edit the item's tags array — so the caller names the operation.
func (*Client) RawChildItems ¶ added in v0.9.0
func (c *Client) RawChildItems(ctx context.Context, library LibraryRef, parentKey string, opts ChildItemsOptions) ([]json.RawMessage, Page, error)
RawChildItems reads one page of complete child item envelopes. It validates only each child's identity, leaving all other Zotero-owned fields untouched.
func (*Client) RawItem ¶ added in v0.9.0
func (c *Client) RawItem(ctx context.Context, library LibraryRef, key string) (json.RawMessage, error)
RawItem reads one complete item envelope, validating only the response shape and requested identity while leaving every other Zotero-owned field untouched.
func (*Client) RawItemWithChildren ¶ added in v0.9.0
func (c *Client) RawItemWithChildren(ctx context.Context, library LibraryRef, key string) (json.RawMessage, []json.RawMessage, error)
RawItemWithChildren reads one item and every direct child, honoring backoff between the parent response and the first child request.
func (*Client) RegisterAttachmentUpload ¶ added in v0.9.0
func (c *Client) RegisterAttachmentUpload(ctx context.Context, library LibraryRef, attachmentKey, uploadKey string) error
RegisterAttachmentUpload makes staged bytes the attachment's managed file.
func (*Client) ReplaceItem ¶ added in v0.8.0
func (c *Client) ReplaceItem(ctx context.Context, op Operation, lib LibraryRef, key string, full json.RawMessage, ifUnmodifiedSince int) error
ReplaceItem overwrites one item with a complete JSON representation (PUT). Fields absent from full are reset to their defaults — unlike PatchItem, which leaves them — so the caller must send the whole object. One field is verified to behave otherwise against the local API: an omitted "tags" is preserved rather than cleared, so a caller that means to strip tags must send "tags": []. (Omitted "collections" is cleared, like ordinary fields.)
func (*Client) RequireWriteCapability ¶ added in v0.9.0
RequireWriteCapability confirms this endpoint can accept writes before the CLI prompts, authorizes, or issues one. On the local endpoint the write API announces itself with a Zotero-Server-ID header on every response (zotero/zotero#5015); a single GET bootstraps it, and its absence means the build predates writes. It returns ErrWriteUnsupported in that case, so a write fails early with an actionable reason instead of a late, opaque 404. The web endpoint has no such probe; its write grants are reported by doctor.
func (*Client) ResolveLibrary ¶
ResolveLibrary maps a CLI-facing selector to a library route on this endpoint.
"", "me", "my", and "user" select the endpoint's own user library. Group selectors may be a numeric group id, "group/<id>", "groups/<id>", or an exact group name. Identity is resolved once (a no-op locally, one /keys/current call on the Web endpoint) and reused for any group lookup.
func (*Client) ServerID ¶ added in v0.6.0
ServerID reports the most recently seen Zotero-Server-ID, or "" if none.
func (*Client) SetLocalKey ¶ added in v0.6.0
SetLocalKey installs a previously obtained (remembered) local API key, so a caller that persisted one need not re-prompt.
func (*Client) SetWriteAuthorizer ¶ added in v0.9.0
func (c *Client) SetWriteAuthorizer(a WriteAuthorizer)
SetWriteAuthorizer installs the authority policy consulted before every write. Installing nil restores deny-by-default: with no authorizer, every write is refused with ErrWriteNotAuthorized, so a write path that never established one cannot reach Zotero.
func (*Client) Stats ¶
Stats returns library-wide counts. It issues one cheap limit=1 request per count and reads the Total-Results header, never paging the actual rows.
func (*Client) UploadAuthorizedAttachment ¶ added in v0.9.0
func (c *Client) UploadAuthorizedAttachment(ctx context.Context, authorization AttachmentUploadAuthorization, body io.Reader, size int64) error
UploadAuthorizedAttachment streams staged bytes to Zotero's key-scoped local receiver.
func (*Client) WebKey ¶ added in v0.5.0
WebKey fetches /keys/current, describing the key this Client authenticates with. It is only valid on the Web endpoint.
A 403 or 404 means the key is missing, revoked, or wrong; both surface as ErrInvalidAPIKey rather than the transport-level status, so the CLI can print one clear message.
type CollectionData ¶
type CollectionData struct {
Key string `json:"key"`
Name string `json:"name"`
ParentCollection json.RawMessage `json:"parentCollection"`
}
CollectionData contains the stable collection fields used for tree rendering.
func (CollectionData) ParentKey ¶
func (d CollectionData) ParentKey() string
ParentKey returns data.parentCollection as a collection key, or "" for top-level collections.
type CollectionPath ¶ added in v0.9.0
type CollectionPath struct {
Key string
Name string
ParentKey string
NumItems int
Segments []CollectionPathSegment
}
CollectionPath is one requested collection and its complete ancestry.
func ResolveCollectionPaths ¶ added in v0.9.0
func ResolveCollectionPaths(envelopes []Envelope, keys []string) ([]CollectionPath, error)
ResolveCollectionPaths resolves requested keys from a complete collection listing. Results preserve request order and duplicates.
type CollectionPathSegment ¶ added in v0.9.0
CollectionPathSegment is one collection in a root-to-leaf path.
type CollectionsOptions ¶
CollectionsOptions controls collection-list requests.
type EndpointKind ¶ added in v0.3.0
type EndpointKind string
EndpointKind distinguishes the endpoints zotgo can be pointed at.
The durable axis is local vs remote, not read vs write: Zotero's Web API already offers remote CRUD, and its Local API is read-only only for now. Each endpoint is its own version and concurrency domain, so an operation is never silently moved between them.
const ( // EndpointLocal is a Zotero 7+ desktop app's HTTP server on this machine. EndpointLocal EndpointKind = "local" // EndpointWeb is the hosted Web API at api.zotero.org, reached with an API // key. Its transport is implemented; the CLI wiring lands with v0.5. EndpointWeb EndpointKind = "web" )
type Envelope ¶
type Envelope struct {
Key string `json:"key"`
Version int `json:"version"`
Library Library `json:"library"`
Links map[string]Link `json:"links"`
Meta map[string]json.RawMessage `json:"meta"`
Data json.RawMessage `json:"data"`
}
Envelope is the common Local API wrapper for items and collections.
Data is intentionally raw: Zotero item fields vary by itemType, and preserving unknown fields is safer than flattening them away.
func (Envelope) AttachmentData ¶ added in v0.9.0
func (e Envelope) AttachmentData() (Attachment, error)
AttachmentData decodes and validates one attachment's data object.
func (Envelope) CollectionData ¶
func (e Envelope) CollectionData() (CollectionData, error)
CollectionData decodes e.Data as Zotero collection JSON.
func (Envelope) CreatorSummary ¶
CreatorSummary returns meta.creatorSummary.
func (Envelope) NoteData ¶ added in v0.9.0
NoteData decodes and validates one note item's data object.
func (Envelope) NumChildren ¶
NumChildren returns meta.numChildren. Missing/non-numeric values return 0.
func (Envelope) ParsedDate ¶
ParsedDate returns meta.parsedDate.
func (*Envelope) UnmarshalJSON ¶ added in v0.7.0
type Group ¶
type Group struct {
ID int64 `json:"id"`
Version int `json:"version"`
Meta GroupMeta `json:"meta"`
Data GroupData `json:"data"`
}
Group is the subset of /api/users/0/groups needed for library selection.
type Health ¶
type Health struct {
// Endpoint identifies what was probed: its kind and address.
Endpoint Profile
// Reachable is the liveness signal both endpoints share: the local Connector
// accepted a connection, or the Web API answered at all (even to reject a key).
Reachable bool
// Local endpoint only.
//
// ZoteroRunning is true when the Connector HTTP server accepted a connection
// (Zotero 7+ is running). ZoteroVersion is its reported version.
// LocalAPIEnabled is true when the Local API serves protected routes rather
// than 403 "Local API is not enabled".
ZoteroRunning bool
ZoteroVersion string
LocalAPIEnabled bool
// ServerID is the Zotero-Server-ID header the Local API returns on every
// response once it has the local write API (zotero/zotero#5015). Its presence
// is the probe signal that this Zotero build supports writes; empty on builds
// that predate the write endpoints.
ServerID string
// Web endpoint only.
//
// KeyValid is true when /keys/current accepted the API key and it resolves to
// a user. WebUserID is that user's id.
KeyValid bool
WebUserID int64
// SchemaVersion and APIVersion are reported by either endpoint on a
// successful protected read.
SchemaVersion string
APIVersion string
// contains filtered or unexported fields
}
Health is a snapshot of whether zotgo can reach the active endpoint and what it may do there. Some fields describe only one endpoint kind; which apply is fixed by Endpoint.Kind.
func (Health) Capabilities ¶ added in v0.3.0
func (h Health) Capabilities() []CapabilityStatus
Capabilities reports what the probed endpoint supports, in a stable order.
Capabilities are derived from the probe rather than discovered by exercising them: zotgo will not issue a speculative write to find out whether writes are allowed. The Web endpoint can report writes honestly because the key's own grants say so; the local endpoint cannot, and says why.
func (Health) Ready ¶
Ready reports whether the active endpoint is usable for reads: locally, that Zotero is running and its Local API is enabled; on the Web API, that the key is valid and grants some library read access.
func (Health) Supports ¶ added in v0.3.0
func (h Health) Supports(c Capability) bool
Supports reports whether the endpoint offers a capability.
type ItemData ¶
type ItemData struct {
Key string `json:"key"`
Version int `json:"version"`
ItemType string `json:"itemType"`
Title string `json:"title"`
Date string `json:"date"`
DateAdded string `json:"dateAdded"`
DateModified string `json:"dateModified"`
// ParentItem is the parent's key on a child item (attachment/note/annotation);
// empty on a top-level item.
ParentItem string `json:"parentItem"`
Creators []Creator `json:"creators"`
Tags []Tag `json:"tags"`
Collections []string `json:"collections"`
}
ItemData contains the stable item fields zotgo needs for display and tests.
func (*ItemData) UnmarshalJSON ¶ added in v0.7.0
type ItemIdentity ¶ added in v0.9.0
ItemIdentity is the small invariant shared by every Zotero item envelope.
func DecodeItemIdentity ¶ added in v0.9.0
func DecodeItemIdentity(raw json.RawMessage) (ItemIdentity, error)
DecodeItemIdentity validates only an item's envelope shape and identity. It deliberately leaves every other Zotero-owned field untouched.
type ItemsOptions ¶
type ItemsOptions struct {
Top bool
Collection string
Tags []string
Limit int
Start int
Query string
Everything bool
ItemType string
// ItemKeys restricts the result to these item keys (`itemKey=`). Combined
// with Top it selects exactly those items; on the unfiltered /items route
// Zotero also returns their children.
ItemKeys []string
}
ItemsOptions controls item-list and search requests.
type KeyWriteResult ¶ added in v0.9.0
type KeyWriteResult struct {
Successful map[string]string
Unchanged map[string]string
Failed map[string]WriteFailure
}
KeyWriteResult decodes only created keys, so callers that need no returned object data are not coupled to unrelated Zotero envelope fields.
type Library ¶
type Library struct {
Type string `json:"type"`
ID int64 `json:"id"`
Name string `json:"name"`
Links map[string]Link `json:"links"`
}
Library identifies the library that owns an envelope.
type LibraryFiles ¶ added in v0.9.0
type LibraryFiles struct {
// ID is the numeric library id (1 is My Library; a group's is its group id).
ID int
// Name is the library name as Zotero reports it.
Name string
// FilesEditable is true when the library accepts attachment files.
FilesEditable bool
}
LibraryFiles reports whether one library the running Zotero can currently file into accepts attachment files. It answers what doctor's endpoint-level local-file-access capability cannot: a group library can be writable yet refuse files (its group has file storage disabled), and that otherwise surfaces only as attachments that silently never appear.
type LibraryRef ¶
LibraryRef is the route-level identity of a Zotero library.
func GroupLibrary ¶
func GroupLibrary(id int64, name string) LibraryRef
GroupLibrary returns the Local API route for a Zotero group library.
func UserLibrary ¶
func UserLibrary() LibraryRef
UserLibrary returns the Local API route for the logged-in user's library.
type Link ¶
type Link struct {
Href string `json:"href"`
Type string `json:"type"`
Title string `json:"title"`
Length *int64 `json:"length"`
AttachmentType string `json:"attachmentType"`
AttachmentSize int64 `json:"attachmentSize"`
}
Link is a Zotero Local API link object. Attachment links include extra fields.
func (*Link) UnmarshalJSON ¶ added in v0.9.0
UnmarshalJSON accepts href:false, which Zotero uses for an imported_file attachment whose metadata exists but whose managed bytes are not registered.
type Note ¶ added in v0.9.0
type Note struct {
Key string
ParentKey string
DateAdded string
DateModified string
Tags []Tag
HTML string
}
Note is one Zotero note item's bounded metadata and exact rich-text HTML.
func DecodeNote ¶ added in v0.9.0
func DecodeNote(raw json.RawMessage) (Note, error)
DecodeNote decodes one note's bounded fields from a raw item envelope.
type Operation ¶ added in v0.9.0
type Operation string
Operation names a single mutating command for write-authorization scoping. The values are the stable, per-command vocabulary a write lease grants against, so least privilege can withhold, say, item.delete while allowing item.patch. They intentionally mirror the CLI's write commands one-to-one.
const ( OpItemCreate Operation = "item.create" OpItemPatch Operation = "item.patch" OpItemReplace Operation = "item.replace" OpItemDelete Operation = "item.delete" OpCollectionCreate Operation = "collection.create" OpCollectionRename Operation = "collection.rename" OpCollectionMove Operation = "collection.move" OpCollectionDelete Operation = "collection.delete" OpTagAdd Operation = "tag.add" OpTagRemove Operation = "tag.remove" OpTagDelete Operation = "tag.delete" // OpAttachmentImport is reserved for the managed-file upload command (#52), // which conforms to the write-lease model once it lands. OpAttachmentImport Operation = "attachment.import" )
type Option ¶ added in v0.3.0
type Option func(*Client)
An Option configures a Client at construction.
func WithHTTPClient ¶ added in v0.3.0
WithHTTPClient makes the Client issue its requests through h, which carries the transport, redirect policy, and timeout. Use it to supply a custom transport for retries, tracing, or tests. A nil h is ignored.
The Client copies h, so later changes to the caller's value — including those made by WithTimeout — do not affect it.
func WithTimeout ¶ added in v0.3.0
WithTimeout bounds each round-trip. It overrides any timeout carried by a client passed to WithHTTPClient, so pass it afterwards to take effect.
type Page ¶
type Page struct {
TotalResults int
NextURL string
LastModifiedVersion string
SchemaVersion string
APIVersion string
// Backoff is the Web API's request to pause before further requests when its
// servers are loaded (the Backoff header). Zero when absent. Pagination loops
// honor it between pages.
Backoff time.Duration
}
Page carries pagination and version headers for a Local API response.
type Profile ¶ added in v0.3.0
type Profile struct {
Kind EndpointKind
BaseURL string
}
Profile is the printable identity of the endpoint a Client talks to: its kind and address, nothing more.
It deliberately carries no credential. The Web API key lives on the Client's Authenticator, not here, so a Profile is always safe to log or embed in machine output without leaking a secret. It also carries no server identity: the Zotero-Server-ID a write-capable build returns is a runtime value the Client caches for writes, not part of the endpoint's stable identity.
func LocalProfile ¶ added in v0.3.0
LocalProfile describes a running Zotero on this machine.
func WebProfile ¶ added in v0.5.0
WebProfile describes the hosted Web API at baseURL (api.zotero.org).
func (Profile) LibraryPrefix ¶ added in v0.5.0
func (p Profile) LibraryPrefix(lib LibraryRef) string
LibraryPrefix is the API path prefix for a library's resources on this endpoint. The Local API namespaces everything under /api and addresses the logged-in user as the "0" sentinel; the Web API omits /api and uses the real numeric user id carried by the LibraryRef.
type Relation ¶ added in v0.9.0
Relation is one outgoing predicate/target edge from an item. Target remains authoritative; TargetKey is only a convenience for strict Zotero item URIs.
func DecodeRelations ¶ added in v0.9.0
func DecodeRelations(raw json.RawMessage) ([]Relation, error)
DecodeRelations returns outgoing relations in stable predicate/target order. Zotero reads use arrays, while its write API also documents one string value.
type StatusError ¶
StatusError preserves an unexpected non-2xx response from Zotero.
func (StatusError) Error ¶
func (e StatusError) Error() string
type WebAccess ¶ added in v0.5.0
type WebAccess struct {
User WebUserAccess `json:"user"`
Groups map[string]WebGroupAccess `json:"groups"`
}
WebAccess is the key's permission grants, split into the user's own library and the groups it can reach.
type WebGroupAccess ¶ added in v0.5.0
WebGroupAccess is what the key may do in a group library.
type WebKey ¶ added in v0.5.0
type WebKey struct {
UserID int64 `json:"userID"`
Username string `json:"username"`
Access WebAccess `json:"access"`
}
WebKey is what the Web API's /keys/current reports about the API key carried on the request: which user it belongs to and what it may reach. It is meaningful only on the Web endpoint; the Local API has no such route and needs no key.
The access grants are the endpoint's own answer to "what can this key do", which is why the Web profile can report capabilities honestly instead of guessing — unlike the local write capability, which no probe can derive.
type WebUserAccess ¶ added in v0.5.0
type WebUserAccess struct {
Library bool `json:"library"`
Files bool `json:"files"`
Notes bool `json:"notes"`
Write bool `json:"write"`
}
WebUserAccess is what the key may do in its owner's personal library.
type WriteAuthorizer ¶ added in v0.9.0
type WriteAuthorizer interface {
AuthorizeWrite(op Operation, lib LibraryRef) error
}
WriteAuthorizer decides whether one write may proceed. It is consulted at the write chokepoint before any mutating request reaches Zotero, so a denial costs no network I/O and fails closed. The returned error, if any, is surfaced to the caller unchanged, so an implementation can distinguish refusal reasons (missing authority, expired, out of scope) with its own sentinels.
func AllowAllWrites ¶ added in v0.9.0
func AllowAllWrites() WriteAuthorizer
AllowAllWrites returns a WriteAuthorizer that permits every write. Callers use it when authority is established out of band — an interactive human answered a confirmation prompt — and tests use it to exercise the write mechanism itself.
type WriteFailure ¶ added in v0.6.0
type WriteFailure struct {
Key string `json:"key"`
Code int `json:"code"`
Message string `json:"message"`
}
WriteFailure explains why one object in a batch was rejected.
type WriteResult ¶ added in v0.6.0
type WriteResult struct {
Successful map[string]Envelope `json:"successful"`
Unchanged map[string]string `json:"unchanged"`
Failed map[string]WriteFailure `json:"failed"`
}
WriteResult is the outcome of a batch write, mirroring the Web API v3 shape the local endpoint reuses: objects that were written, ones left unchanged because they already matched, and ones that failed, each keyed by the object's index in the request.
func (WriteResult) FirstFailure ¶ added in v0.6.0
func (r WriteResult) FirstFailure() WriteFailure
FirstFailure returns a representative failure, or the zero value when none.
func (WriteResult) Ok ¶ added in v0.6.0
func (r WriteResult) Ok() bool
Ok reports whether every object in the batch was accepted.