api

package
v0.2.0 Latest Latest
Warning

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

Go to latest
Published: Jul 14, 2026 License: MIT Imports: 8 Imported by: 0

Documentation

Overview

Package api wraps the Hardcover GraphQL API.

Index

Constants

View Source
const APIURL = "https://api.hardcover.app/v1/graphql"

APIURL is the Hardcover GraphQL endpoint.

View Source
const JournalFetchLimit = 100

JournalFetchLimit is the page size for journal queries.

View Source
const LibraryFetchLimit = 1000

LibraryFetchLimit is the page size for library-style queries.

View Source
const MutationInsertUserBook = `
mutation ($object: UserBookCreateInput!) {
  insert_user_book(object: $object) {
    id
    error
  }
}
`

MutationInsertUserBook adds a book to the user's library.

View Source
const MutationInsertUserBookRead = `` /* 161-byte string literal not displayed */

MutationInsertUserBookRead creates a new user_book_read.

View Source
const MutationUpdateUserBook = `
mutation ($id: Int!, $object: UserBookUpdateInput!) {
  update_user_book(id: $id, object: $object) {
    id
  }
}
`

MutationUpdateUserBook updates status_id and/or rating.

View Source
const MutationUpdateUserBookRead = `
mutation ($id: Int!, $object: DatesReadInput!) {
  update_user_book_read(id: $id, object: $object) {
    id
  }
}
`

MutationUpdateUserBookRead updates the active user_book_read.

View Source
const QueryActiveRead = `` /* 259-byte string literal not displayed */

QueryActiveRead fetches the active user_book_read for a user_book.

View Source
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.

View Source
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.

View Source
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.

View Source
const QueryGoalsActive = `` /* 242-byte string literal not displayed */

QueryGoalsActive lists only non-archived goals.

View Source
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.

View Source
const QueryJournals = `` /* 343-byte string literal not displayed */

QueryJournals fetches reading journal events for export/daily.

View Source
const QueryLibrary = `` /* 402-byte string literal not displayed */

QueryLibrary is the user_books query used by the library command.

View Source
const QueryLibraryNoStatus = `` /* 355-byte string literal not displayed */

QueryLibraryNoStatus is the variant when no --status filter is applied.

View Source
const QueryMe = `
query {
  me {
    id
    username
    books_count
  }
}
`
View Source
const QueryProgress = `` /* 413-byte string literal not displayed */

QueryProgress is used by the progress command.

View Source
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.

View Source
const QuerySearch = `` /* 136-byte string literal not displayed */

QuerySearch hits Hardcover's search endpoint.

View Source
const QueryStats = `` /* 896-byte string literal not displayed */

QueryStats returns aggregates and active goals.

View Source
const QueryUserBookByID = `` /* 157-byte string literal not displayed */

QueryUserBookByID is used by log --id to fetch a single user_book.

View Source
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.

View Source
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 Author

type Author struct {
	Name string `json:"name"`
}

Author is a book contributor.

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

type Client struct {
	HTTPClient *http.Client
	APIURL     string
	Token      string
}

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 New

func New(token string) *Client

New returns a Client configured with sensible defaults.

func (*Client) GQL

func (c *Client) GQL(ctx context.Context, query string, variables map[string]any, target any) error

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 Edition

type Edition struct {
	ID    int `json:"id"`
	Pages int `json:"pages"`
}

Edition is a particular edition of a book (pages, etc.).

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 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.).

type UserBookRead

type UserBookRead struct {
	ID            int     `json:"id"`
	ProgressPages int     `json:"progress_pages"`
	StartedAt     *string `json:"started_at"`
	FinishedAt    *string `json:"finished_at"`
}

UserBookRead is an in-progress reading session.

Jump to

Keyboard shortcuts

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