Documentation
¶
Overview ¶
Package api wraps the Hardcover GraphQL API.
Index ¶
Constants ¶
const APIURL = "https://api.hardcover.app/v1/graphql"
APIURL is the Hardcover GraphQL endpoint.
const JournalFetchLimit = 100
JournalFetchLimit is the page size for journal queries.
const LibraryFetchLimit = 1000
LibraryFetchLimit is the page size for library-style queries.
const MutationInsertUserBook = `
mutation ($object: UserBookCreateInput!) {
insert_user_book(object: $object) {
id
error
}
}
`
MutationInsertUserBook adds a book to the user's library.
const MutationInsertUserBookRead = `` /* 161-byte string literal not displayed */
MutationInsertUserBookRead creates a new user_book_read.
const MutationUpdateUserBook = `
mutation ($id: Int!, $object: UserBookUpdateInput!) {
update_user_book(id: $id, object: $object) {
id
}
}
`
MutationUpdateUserBook updates status_id and/or rating.
const MutationUpdateUserBookRead = `
mutation ($id: Int!, $object: DatesReadInput!) {
update_user_book_read(id: $id, object: $object) {
id
}
}
`
MutationUpdateUserBookRead updates the active user_book_read.
const QueryActiveRead = `` /* 259-byte string literal not displayed */
QueryActiveRead fetches the active user_book_read for a user_book.
const QueryBookEditions = `` /* 386-byte string literal not displayed */
QueryBookEditions fetches editions for a given book, ordered by popularity (users_count). Used by the add command so the user can pick a specific edition.
const QueryBookTitles = `` /* 181-byte string literal not displayed */
QueryBookTitles fetches id and title for every user book, paginated. Used by export to build the book_id -> title mapping.
const QueryBookTitlesAndPages = `` /* 187-byte string literal not displayed */
QueryBookTitlesAndPages fetches id, title, and pages for every user book, paginated. Used by daily to build book metadata.
const QueryGoalsActive = `` /* 242-byte string literal not displayed */
QueryGoalsActive lists only non-archived goals.
const QueryGoalsAll = `` /* 216-byte string literal not displayed */
QueryGoalsAll lists every goal (including archived). Caller decides whether to filter archived in code or use QueryGoalsActive.
const QueryJournals = `` /* 343-byte string literal not displayed */
QueryJournals fetches reading journal events for export/daily.
const QueryLibrary = `` /* 402-byte string literal not displayed */
QueryLibrary is the user_books query used by the library command.
const QueryLibraryNoStatus = `` /* 355-byte string literal not displayed */
QueryLibraryNoStatus is the variant when no --status filter is applied.
const QueryMe = `
query {
me {
id
username
books_count
}
}
`
const QueryProgress = `` /* 413-byte string literal not displayed */
QueryProgress is used by the progress command.
const QueryReadBooksPages = `` /* 223-byte string literal not displayed */
QueryReadBooksPages fetches just edition/book pages for read books, paginated. Used by the stats command to compute total pages.
const QuerySearch = `` /* 136-byte string literal not displayed */
QuerySearch hits Hardcover's search endpoint.
const QueryStats = `` /* 896-byte string literal not displayed */
QueryStats returns aggregates and active goals.
const QueryUserBookByID = `` /* 157-byte string literal not displayed */
QueryUserBookByID is used by log --id to fetch a single user_book.
const QueryUserBooksByTitle = `` /* 304-byte string literal not displayed */
QueryUserBooksByTitle is used by log to fuzzy-match a book. Hardcover restricts _ilike on book.title, so we fetch the user's library and filter on the client side. The book fields are minimally populated to keep payload size reasonable.
const RequestTimeout = 30 * time.Second
RequestTimeout is the default per-request timeout.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Aggregate ¶
type Aggregate struct {
Count int `json:"count"`
}
Aggregate is the aggregate result of a count query.
type AggregateWithAvg ¶
type AggregateWithAvg struct {
Count int `json:"count"`
Avg *struct {
Rating float64 `json:"rating"`
} `json:"avg"`
}
AggregateWithAvg is the aggregate result of a count+avg query.
type Book ¶
type Book struct {
ID int `json:"id"`
Title string `json:"title"`
Pages int `json:"pages"`
Contributions []Contribution `json:"contributions"`
}
Book is a title in Hardcover's catalog.
type Client ¶
Client is a Hardcover GraphQL client. The HTTPClient field is exported so tests can inject *http.Client with a custom Transport. The token is captured at construction; callers should not mutate it.
func (*Client) GQL ¶
GQL executes a GraphQL query/mutation against the API and decodes the response into target. The context is forwarded to the HTTP request so callers can wire timeouts or cancellation (e.g. Ctrl-C).
Errors are wrapped with the appropriate sentinel:
- 401/403 -> errs.ErrAuthFailed
- timeout / refused -> errs.ErrNetError
- non-JSON body -> errs.ErrNetError
- API errors[] -> errs.ErrInvalid
- 4xx (other) -> errs.ErrInvalid
- 5xx -> errs.ErrNetError
type Contribution ¶
type Contribution struct {
Author Author `json:"author"`
}
Contribution associates an author with a book.
type EditionResult ¶
type EditionResult struct {
ID int `json:"id"`
Pages *int `json:"pages"`
EditionFormat *string `json:"edition_format"`
PhysicalFormat *string `json:"physical_format"`
ReleaseYear *int `json:"release_year"`
Title *string `json:"title"`
ISBN13 *string `json:"isbn_13"`
ISBN10 *string `json:"isbn_10"`
UsersCount int `json:"users_count"`
Publisher *struct{ Name string } `json:"publisher"`
Language *struct{ Language string } `json:"language"`
ReadingFormat *struct{ Format string } `json:"reading_format"`
}
EditionResult is a decoded edition from the editions query.
type Goal ¶
type Goal struct {
ID int `json:"id"`
Metric string `json:"metric"`
Goal float64 `json:"goal"`
Progress float64 `json:"progress"`
State string `json:"state"`
StartDate string `json:"start_date"`
EndDate string `json:"end_date"`
Description *string `json:"description"`
}
Goal is a reading goal.
type ReadingJournal ¶
type ReadingJournal struct {
BookID int `json:"book_id"`
ActionAt string `json:"action_at"`
Metadata map[string]any `json:"metadata"`
}
ReadingJournal is a reading event.
type Search ¶
type Search struct {
Results SearchResults `json:"results"`
}
Search is the search query response.
type SearchHit ¶
type SearchHit struct {
Document json.RawMessage `json:"document"`
}
SearchHit is a single search result.
type SearchResult ¶
type SearchResult struct {
ID string
Title string
AuthorNames []string
Pages *int
ReleaseYear *int
Rating float64
}
SearchResult is a decoded book from the catalog search. Populated manually in decodeSearchHit — not unmarshaled from JSON.
type SearchResults ¶
type SearchResults struct {
Hits []SearchHit `json:"hits"`
}
SearchResults is the inner payload of a search query.
type User ¶
type User struct {
ID int `json:"id"`
Username string `json:"username"`
BooksCount int `json:"books_count"`
}
User is the authenticated user (from the me query).
type UserBook ¶
type UserBook struct {
ID int `json:"id"`
EditionID *int `json:"edition_id"`
StatusID int `json:"status_id"`
Rating float64 `json:"rating"`
DateAdded string `json:"date_added"`
Owned bool `json:"owned"`
Edition *Edition `json:"edition"`
Book Book `json:"book"`
// Populated for the progress command: the active reading session.
UserBookReads []UserBookRead `json:"user_book_reads"`
}
UserBook is a user's relationship with a book (status, rating, etc.).