aboutsummaryrefslogtreecommitdiffstats
path: root/lulu.go
diff options
context:
space:
mode:
Diffstat (limited to 'lulu.go')
-rw-r--r--lulu.go411
1 files changed, 220 insertions, 191 deletions
diff --git a/lulu.go b/lulu.go
index f79ebe0..aca07da 100644
--- a/lulu.go
+++ b/lulu.go
@@ -31,7 +31,159 @@ const (
printJobsPath = "/print-jobs"
)
-type Client struct {
+// A Client connects to the Lulu API server.
+type Client interface {
+ // StartInteriorValidation starts a server-side validation job for the
+ // interior file located at srcUrl using manufacturing settings given
+ // by mfg. It returns the ID of the job. Use
+ // [Client.GetInteriorValidation] to poll the status of the job.
+ //
+ // https://api.lulu.com/docs/#tag/Files-validation/operation/Validate-Interior_create
+ StartInteriorValidation(srcUrl string, mfg PkgId) (uint, error)
+
+ // StartInteriorValidationBasic is like
+ // [Client.StartInteriorValidation] but without the optional
+ // pod_package_id.
+ //
+ // https://api.lulu.com/docs/#tag/Files-validation/operation/Validate-Interior_create
+ StartInteriorValidationBasic(srcUrl string) (uint, error)
+
+ // GetInteriorValidation retrieves information about an interior file
+ // validation job that was started by ValidateInterior().
+ //
+ // https://api.lulu.com/docs/#tag/Files-validation/operation/Validate-Interior_read
+ GetInteriorValidation(id uint) (InteriorValidation, error)
+
+ // CoverDimensions calculates the required dimensions of the cover for
+ // a book with the given manufacturing settings and number of pages.
+ // The returned dimensions are given in the specified units of
+ // measurement.
+ //
+ // https://api.lulu.com/docs/#tag/Files-validation/operation/Cover-Dimensions_create
+ CoverDimensions(mfg PkgId, npages uint, unit Unit) (CoverDimensions, error)
+
+ // StartCoverValidation starts a server-side validation job for the
+ // cover file located at srcUrl, returning the job ID. mfg is the
+ // manufacturing settings of the book, and npages is the number of
+ // interior pages. Use [Client.GetCoverValidation] to poll the status
+ // of the job.
+ //
+ // https://api.lulu.com/docs/#tag/Files-validation/operation/Validate-Cover_create
+ StartCoverValidation(srcUrl string, mfg PkgId, npages uint) (uint, error)
+
+ // GetCoverValidiation retrieves information about a cover file
+ // validation job that was started by ValidateCover().
+ //
+ // https://api.lulu.com/docs/#tag/Files-validation/operation/Validate-Cover_read
+ GetCoverValidation(id uint) (CoverValidation, error)
+
+ // Cost calculates the cost of a hypothetical print order without
+ // actually creating a print job.
+ //
+ // https://api.lulu.com/docs/#tag/Print-Job-Cost-Calculations/operation/Print-Job-cost-calculations_create
+ Cost(items []CostLineItem, addr ShippingAddress, shipOpt ShippingLevel) (Cost, ShippingAddressValidation, error)
+
+ // Print creates a new print job.
+ //
+ // contact: Email address that should be contacted if
+ // questions regarding the Print-Job arise. Lulu recommends to
+ // use the email of a person who is responsible for placing
+ // the Print-Job like a developer or business owner.
+ //
+ // externalId: Arbitrary string to identify and connect a
+ // print job to your systems. Set it to an order number, a
+ // purchase order or whatever else works for your particular
+ // use case.
+ //
+ // productionDelay: Delay before a newly created Print-Job is
+ // sent to production. Must be
+ // [[MinProductionDelay],[MaxProductionDelay]]. This gives
+ // some time for the order to be cancelled before the books
+ // are printed. Once production has started, orders cannot be
+ // canceled anymore.
+ //
+ // addr: The postal address of the customer that the order
+ // will be sent to.
+ //
+ // shipOpt: Shipping method.
+ //
+ // items: List of books to print.
+ //
+ // https://api.lulu.com/docs/#tag/Print-Jobs/operation/Print-Jobs_create
+ Print(contact EmailAddress, externalId string, productionDelay time.Duration, addr ShippingAddress, shipOpt ShippingLevel, items []Printable) (PrintJob, error)
+
+ // Reprint creates a print job, printing books whose PrintableIds are
+ // known from (one or more) prior calls to [Client.Print].
+ //
+ // https://api.lulu.com/docs/#tag/Print-Jobs/operation/Print-Jobs_reprint
+ Reprint(contact EmailAddress, externalId string, productionDelay time.Duration, addr ShippingAddress, shipOpt ShippingLevel, items []Reprintable) (PrintJob, error)
+
+ // Job retrieves the print job with the given ID, which is a
+ // [PrintJob.Id] returned by [Client.Print] or [Client.Reprint].
+ //
+ // https://api.lulu.com/docs/#tag/Print-Jobs/operation/Print-Jobs_read
+ Job(id uint64) (PrintJob, error)
+
+ // Jobs retrieves a list of all print jobs that have been created,
+ // filtered by a set of optional query parameters.
+ //
+ // https://api.lulu.com/docs/#tag/Print-Jobs/operation/Print-Jobs_list
+ Jobs(queries ...PrintJobQuery) ([]PrintJob, error)
+
+ // Cancel cancels the print job with the given ID. jobId is from a
+ // [PrintJob] returned by [Client.Print] or [Client.Reprint].
+ //
+ // https://api.lulu.com/docs/#tag/Print-Jobs/operation/Print-Jobs_status_cancel
+ Cancel(jobId uint64) error
+}
+
+// ValidateInterior starts a server-side validation job for the given
+// interior file and polls its status until it finishes or the context
+// expires. See [Client.StartInteriorValidation], [Client.GetInteriorValidation],
+// and [PollPeriod].
+func ValidateInterior(ctx context.Context, c Client, srcUrl string, mfg PkgId) (InteriorValidation, error) {
+ id, err := c.StartInteriorValidation(srcUrl, mfg)
+ if err != nil {
+ return InteriorValidation{}, err
+ }
+ return pollInteriorValidation(ctx, c, id, InteriorStatusNormalized)
+}
+
+// ValidateInteriorBasic is like [Client.ValidateInterior] but without the
+// optional pod_package_id.
+func ValidateInteriorBasic(ctx context.Context, c Client, srcUrl string) (InteriorValidation, error) {
+ id, err := c.StartInteriorValidationBasic(srcUrl)
+ if err != nil {
+ return InteriorValidation{}, err
+ }
+ return pollInteriorValidation(ctx, c, id, InteriorStatusValidated)
+}
+
+func pollInteriorValidation(ctx context.Context, c Client, id uint, wantStatus InteriorValidationStatus) (InteriorValidation, error) {
+ return poll(ctx, func() (InteriorValidation, bool, error) {
+ val, err := c.GetInteriorValidation(id)
+ done := val.Status == wantStatus ||
+ val.Status == InteriorStatusError
+ return val, done, err
+ })
+}
+
+// ValidateCover starts a server-side validation job for the given
+// cover file and polls its status until it finishes or the context
+// expires. See [Client.StartCoverValidation],
+// [Client.GetCoverValidation], and [PollPeriod].
+func ValidateCover(ctx context.Context, c Client, srcUrl string, mfg PkgId, npages uint) (CoverValidation, error) {
+ id, err := c.StartCoverValidation(srcUrl, mfg, npages)
+ if err != nil {
+ return CoverValidation{}, err
+ }
+ return poll(ctx, func() (CoverValidation, bool, error) {
+ val, err := c.GetCoverValidation(id)
+ return val, val.Status.IsFinal(), err
+ })
+}
+
+type client struct {
ctx context.Context
c *http.Client
apiUrl string
@@ -49,17 +201,17 @@ type Credentials struct {
//
// ctx is used by the OAuth2 client. If you don't care about this, use
// [context.Background]. See [clientcredentials.Config.Client].
-func NewClient(ctx context.Context, creds Credentials) (*Client, error) {
+func NewClient(ctx context.Context, creds Credentials) (Client, error) {
return newClient(ctx, creds, production, productionKeyPage)
}
// NewClient creates a client that will connect to the sandbox API
// server. See [NewClient].
-func NewSandboxClient(ctx context.Context, creds Credentials) (*Client, error) {
+func NewSandboxClient(ctx context.Context, creds Credentials) (Client, error) {
return newClient(ctx, creds, sandbox, sandboxKeyPage)
}
-func newClient(ctx context.Context, creds Credentials, apiUrl, keyPageUrl string) (*Client, error) {
+func newClient(ctx context.Context, creds Credentials, apiUrl, keyPageUrl string) (*client, error) {
tokenUrl, err := url.JoinPath(apiUrl, tokenPath)
if err != nil {
return nil, pkgErrf(err, "error creating client")
@@ -70,50 +222,10 @@ func newClient(ctx context.Context, creds Credentials, apiUrl, keyPageUrl string
ClientSecret: creds.Secret,
TokenURL: tokenUrl,
}
- return &Client{ctx, cfg.Client(ctx), apiUrl, keyPageUrl}, nil
-}
-
-// Context returns the client's context.
-func (c *Client) Context() context.Context { return c.ctx }
-
-// ValidateInterior starts a server-side validation job for the given
-// interior file and polls its status until it finishes or the context
-// expires. See [Client.StartInteriorValidation], [Client.GetInteriorValidation],
-// and [PollPeriod].
-func (c *Client) ValidateInterior(ctx context.Context, srcUrl string, mfg PkgId) (InteriorValidation, error) {
- id, err := c.StartInteriorValidation(srcUrl, mfg)
- if err != nil {
- return InteriorValidation{}, err
- }
- return c.pollInteriorValidation(ctx, id, InteriorStatusNormalized)
-}
-
-// ValidateInteriorBasic is like [Client.ValidateInterior] but without the
-// optional pod_package_id.
-func (c *Client) ValidateInteriorBasic(ctx context.Context, srcUrl string) (InteriorValidation, error) {
- id, err := c.StartInteriorValidationBasic(srcUrl)
- if err != nil {
- return InteriorValidation{}, err
- }
- return c.pollInteriorValidation(ctx, id, InteriorStatusValidated)
-}
-
-func (c *Client) pollInteriorValidation(ctx context.Context, id uint, wantStatus InteriorValidationStatus) (InteriorValidation, error) {
- return poll(ctx, func() (InteriorValidation, bool, error) {
- val, err := c.GetInteriorValidation(id)
- done := val.Status == wantStatus ||
- val.Status == InteriorStatusError
- return val, done, err
- })
+ return &client{ctx, cfg.Client(ctx), apiUrl, keyPageUrl}, nil
}
-// StartInteriorValidation starts a server-side validation job for the
-// interior file located at srcUrl using manufacturing settings given by
-// mfg. It returns the ID of the job. Use [Client.GetInteriorValidation] to poll
-// the status of the job.
-//
-// https://api.lulu.com/docs/#tag/Files-validation/operation/Validate-Interior_create
-func (c *Client) StartInteriorValidation(srcUrl string, mfg PkgId) (uint, error) {
+func (c *client) StartInteriorValidation(srcUrl string, mfg PkgId) (uint, error) {
id, err := c.startInteriorValidation(validateInteriorReq{srcUrl, mfg})
if err != nil {
return 0, pkgErr(err)
@@ -121,11 +233,7 @@ func (c *Client) StartInteriorValidation(srcUrl string, mfg PkgId) (uint, error)
return id, nil
}
-// StartInteriorValidationBasic is like [Client.StartInteriorValidation] but
-// without the optional pod_package_id.
-//
-// https://api.lulu.com/docs/#tag/Files-validation/operation/Validate-Interior_create
-func (c *Client) StartInteriorValidationBasic(srcUrl string) (uint, error) {
+func (c *client) StartInteriorValidationBasic(srcUrl string) (uint, error) {
id, err := c.startInteriorValidation(validateInteriorBasicReq{srcUrl})
if err != nil {
return 0, pkgErr(err)
@@ -133,17 +241,13 @@ func (c *Client) StartInteriorValidationBasic(srcUrl string) (uint, error) {
return id, nil
}
-func (c *Client) startInteriorValidation(payload any) (uint, error) {
+func (c *client) startInteriorValidation(payload any) (uint, error) {
var val InteriorValidation
err := c.postDecode(validateInteriorPath, payload, http.StatusCreated, &val)
return val.Id, err
}
-// GetInteriorValidation retrieves information about an interior file
-// validation job that was started by ValidateInterior().
-//
-// https://api.lulu.com/docs/#tag/Files-validation/operation/Validate-Interior_read
-func (c *Client) GetInteriorValidation(id uint) (InteriorValidation, error) {
+func (c *client) GetInteriorValidation(id uint) (InteriorValidation, error) {
path, err := url.JoinPath(validateInteriorPath, fmt.Sprint(id))
if err != nil {
return InteriorValidation{}, pkgErr(err)
@@ -155,12 +259,7 @@ func (c *Client) GetInteriorValidation(id uint) (InteriorValidation, error) {
return val, nil
}
-// CoverDimensions calculates the required dimensions of the cover for a
-// book with the given manufacturing settings and number of pages. The
-// returned dimensions are given in the specified units of measurement.
-//
-// https://api.lulu.com/docs/#tag/Files-validation/operation/Cover-Dimensions_create
-func (c *Client) CoverDimensions(mfg PkgId, npages uint, unit Unit) (CoverDimensions, error) {
+func (c *client) CoverDimensions(mfg PkgId, npages uint, unit Unit) (CoverDimensions, error) {
payload := coverDimensionsReq{mfg, npages, unit}
var dims CoverDimensions
err := c.postDecode(coverDimensionsPath, payload, http.StatusCreated, &dims)
@@ -170,29 +269,7 @@ func (c *Client) CoverDimensions(mfg PkgId, npages uint, unit Unit) (CoverDimens
return dims, nil
}
-// ValidateCover starts a server-side validation job for the given
-// cover file and polls its status until it finishes or the context
-// expires. See [Client.StartCoverValidation],
-// [Client.GetCoverValidation], and [PollPeriod].
-func (c *Client) ValidateCover(ctx context.Context, srcUrl string, mfg PkgId, npages uint) (CoverValidation, error) {
- id, err := c.StartCoverValidation(srcUrl, mfg, npages)
- if err != nil {
- return CoverValidation{}, err
- }
- return poll(ctx, func() (CoverValidation, bool, error) {
- val, err := c.GetCoverValidation(id)
- return val, val.Status.IsFinal(), err
- })
-}
-
-// StartCoverValidation starts a server-side validation job for the
-// cover file located at srcUrl, returning the job ID. mfg is the
-// manufacturing settings of the book, and npages is the number of
-// interior pages. Use [Client.GetCoverValidation] to poll the status
-// of the job.
-//
-// https://api.lulu.com/docs/#tag/Files-validation/operation/Validate-Cover_create
-func (c *Client) StartCoverValidation(srcUrl string, mfg PkgId, npages uint) (uint, error) {
+func (c *client) StartCoverValidation(srcUrl string, mfg PkgId, npages uint) (uint, error) {
payload := validateCoverReq{srcUrl, mfg, npages}
var val CoverValidation
err := c.postDecode(validateCoverPath, payload, http.StatusCreated, &val)
@@ -202,11 +279,7 @@ func (c *Client) StartCoverValidation(srcUrl string, mfg PkgId, npages uint) (ui
return val.Id, nil
}
-// GetCoverValidiation retrieves information about a cover file
-// validation job that was started by ValidateCover().
-//
-// https://api.lulu.com/docs/#tag/Files-validation/operation/Validate-Cover_read
-func (c *Client) GetCoverValidation(id uint) (CoverValidation, error) {
+func (c *client) GetCoverValidation(id uint) (CoverValidation, error) {
path, err := url.JoinPath(validateCoverPath, fmt.Sprint(id))
if err != nil {
return CoverValidation{}, pkgErr(err)
@@ -218,11 +291,7 @@ func (c *Client) GetCoverValidation(id uint) (CoverValidation, error) {
return val, nil
}
-// Cost calculates the cost of a hypothetical print order without
-// actually creating a print job.
-//
-// https://api.lulu.com/docs/#tag/Print-Job-Cost-Calculations/operation/Print-Job-cost-calculations_create
-func (c *Client) Cost(items []CostLineItem, addr ShippingAddress, shipOpt ShippingLevel) (Cost, ShippingAddressValidation, error) {
+func (c *client) Cost(items []CostLineItem, addr ShippingAddress, shipOpt ShippingLevel) (Cost, ShippingAddressValidation, error) {
payload := costReq{items, addr, shipOpt}
var resp costResp
err := c.postDecode(printJobCostPath, payload, http.StatusCreated, &resp)
@@ -232,83 +301,7 @@ func (c *Client) Cost(items []CostLineItem, addr ShippingAddress, shipOpt Shippi
return resp.cost(), resp.AddressValidation, nil
}
-// Jobs retrieves a list of all print jobs that have been created,
-// filtered by a set of optional query parameters.
-//
-// https://api.lulu.com/docs/#tag/Print-Jobs/operation/Print-Jobs_list
-func (c *Client) Jobs(queries ...PrintJobQuery) ([]PrintJob, error) {
- var q printJobQueries
- q.apply(queries...)
- qvals := q.vals()
-
- var jobs []PrintJob
- var cnt uint
- for page := 1; ; page++ {
- qvals.Set("page", fmt.Sprint(page))
- var resp jobsResp
- if err := c.getQueryDecode(printJobsPath, qvals, &resp); err != nil {
- return jobs, pkgErr(err)
- }
-
- cnt = resp.Count
- if len(resp.Results) == 0 && resp.Next != "" {
- return jobs, pkgErr(fmt.Errorf("no results on this page, but server returned a next page: %s", resp.Next))
- }
- if len(resp.Results) > 0 {
- jobs = append(jobs, resp.Results...)
- }
- if len(resp.Results) == 0 || len(resp.Next) == 0 {
- break
- }
- }
- if uint(len(jobs)) != cnt {
- return jobs, pkgErr(fmt.Errorf("expected %d jobs, got %d", cnt, len(jobs)))
- }
- return jobs, nil
-}
-
-// Job retrieves the print job with the given ID.
-//
-// https://api.lulu.com/docs/#tag/Print-Jobs/operation/Print-Jobs_read
-func (c *Client) Job(id uint64) (PrintJob, error) {
- var job PrintJob
- path, err := url.JoinPath(printJobsPath, fmt.Sprint(id))
- if err != nil {
- return job, pkgErr(err)
- }
- if err := c.getDecode(path, &job); err != nil {
- return job, pkgErr(err)
- }
- return job, nil
-}
-
-// Print creates a new print job.
-//
-// contact: Email address that should be contacted if questions
-// regarding the Print-Job arise. Lulu recommends to use the
-// email of a person who is responsible for placing the Print-Job
-// like a developer or business owner.
-//
-// externalId: Arbitrary string to identify and connect a print
-// job to your systems. Set it to an order number, a purchase
-// order or whatever else works for your particular use case.
-//
-// productionDelay: Delay before a newly created Print-Job is
-// sent to production. Minimum is 60 minutes, maximum is 2880
-// minutes (=48 hours). As most cancellation requests occur right
-// after an order has been placed, it makes sense to wait for
-// some time before sending an order to production. Once
-// production has started, orders cannot be canceled anymore.
-//
-// addr: The postal address of the customer that the order will
-// be sent to.
-//
-// shipOpt: Shipping method.
-//
-// items: List of books to print.
-//
-// https://api.lulu.com/docs/#tag/Print-Jobs/operation/Print-Jobs_create
-func (c *Client) Print(contact EmailAddress, externalId string, productionDelay time.Duration, addr ShippingAddress, shipOpt ShippingLevel, items []Printable) (PrintJob, error) {
+func (c *client) Print(contact EmailAddress, externalId string, productionDelay time.Duration, addr ShippingAddress, shipOpt ShippingLevel, items []Printable) (PrintJob, error) {
job, err := print(c, contact, externalId, productionDelay, addr, shipOpt, items)
if err != nil {
err = pkgErr(err)
@@ -316,11 +309,7 @@ func (c *Client) Print(contact EmailAddress, externalId string, productionDelay
return job, err
}
-// Reprint creates a print job, printing books whose PrintableIds are
-// known from a prior order. See also: Print().
-//
-// https://api.lulu.com/docs/#tag/Print-Jobs/operation/Print-Jobs_reprint
-func (c *Client) Reprint(contact EmailAddress, externalId string, productionDelay time.Duration, addr ShippingAddress, shipOpt ShippingLevel, items []Reprintable) (PrintJob, error) {
+func (c *client) Reprint(contact EmailAddress, externalId string, productionDelay time.Duration, addr ShippingAddress, shipOpt ShippingLevel, items []Reprintable) (PrintJob, error) {
job, err := print(c, contact, externalId, productionDelay, addr, shipOpt, items)
if err != nil {
err = pkgErr(err)
@@ -328,7 +317,7 @@ func (c *Client) Reprint(contact EmailAddress, externalId string, productionDela
return job, err
}
-func print[P Printable | Reprintable](c *Client, contact EmailAddress, externalId string, productionDelay time.Duration, addr ShippingAddress, shipOpt ShippingLevel, items []P) (PrintJob, error) {
+func print[P Printable | Reprintable](c *client, contact EmailAddress, externalId string, productionDelay time.Duration, addr ShippingAddress, shipOpt ShippingLevel, items []P) (PrintJob, error) {
if err := verifyProductionDelay(productionDelay); err != nil {
return PrintJob{}, err
}
@@ -353,11 +342,51 @@ func verifyProductionDelay(delay time.Duration) error {
return nil
}
-// Cancel cancels the print job with the given ID.
-//
-// https://api.lulu.com/docs/#tag/Print-Jobs/operation/Print-Jobs_status_cancel
-func (c *Client) Cancel(id uint64) error {
- path, err := url.JoinPath(printJobsPath, fmt.Sprint(id), "status")
+func (c *client) Job(id uint64) (PrintJob, error) {
+ var job PrintJob
+ path, err := url.JoinPath(printJobsPath, fmt.Sprint(id))
+ if err != nil {
+ return job, pkgErr(err)
+ }
+ if err := c.getDecode(path, &job); err != nil {
+ return job, pkgErr(err)
+ }
+ return job, nil
+}
+
+func (c *client) Jobs(queries ...PrintJobQuery) ([]PrintJob, error) {
+ var q printJobQueries
+ q.apply(queries...)
+ qvals := q.vals()
+
+ var jobs []PrintJob
+ var cnt uint
+ for page := 1; ; page++ {
+ qvals.Set("page", fmt.Sprint(page))
+ var resp jobsResp
+ if err := c.getQueryDecode(printJobsPath, qvals, &resp); err != nil {
+ return jobs, pkgErr(err)
+ }
+
+ cnt = resp.Count
+ if len(resp.Results) == 0 && resp.Next != "" {
+ return jobs, pkgErr(fmt.Errorf("no results on this page, but server returned a next page: %s", resp.Next))
+ }
+ if len(resp.Results) > 0 {
+ jobs = append(jobs, resp.Results...)
+ }
+ if len(resp.Results) == 0 || len(resp.Next) == 0 {
+ break
+ }
+ }
+ if uint(len(jobs)) != cnt {
+ return jobs, pkgErr(fmt.Errorf("expected %d jobs, got %d", cnt, len(jobs)))
+ }
+ return jobs, nil
+}
+
+func (c *client) Cancel(jobId uint64) error {
+ path, err := url.JoinPath(printJobsPath, fmt.Sprint(jobId), "status")
if err != nil {
return pkgErr(err)
}
@@ -367,18 +396,18 @@ func (c *Client) Cancel(id uint64) error {
return pkgErr(err)
}
if status.Status != OrderCanceled {
- return pkgErr(fmt.Errorf("cancel job %d: expected %s, got %s", id, OrderCanceled, status.Status))
+ return pkgErr(fmt.Errorf("cancel job %d: expected %s, got %s", jobId, OrderCanceled, status.Status))
}
return nil
}
// getDecode sends a GET request and unmarshals the response.
-func (c *Client) getDecode(path string, v any) error {
+func (c *client) getDecode(path string, v any) error {
return c.getQueryDecode(path, url.Values{}, v)
}
// getQueryDecode sends a GET path?query request and unmarshals the response into v.
-func (c *Client) getQueryDecode(path string, query url.Values, v any) error {
+func (c *client) getQueryDecode(path string, query url.Values, v any) error {
url, err := c.url(path)
if err != nil {
return err
@@ -397,7 +426,7 @@ func (c *Client) getQueryDecode(path string, query url.Values, v any) error {
}
// postDecode sends a POST request and unmarshals the response.
-func (c *Client) postDecode(path string, payload any, wantStatus int, v any) error {
+func (c *client) postDecode(path string, payload any, wantStatus int, v any) error {
resp, err := c.post(path, payload)
if err != nil {
return err
@@ -409,7 +438,7 @@ func (c *Client) postDecode(path string, payload any, wantStatus int, v any) err
return decodeResponse(resp, v)
}
-func (c *Client) post(path string, payload any) (*http.Response, error) {
+func (c *client) post(path string, payload any) (*http.Response, error) {
body, err := json.Marshal(payload)
if err != nil {
return nil, errEncReq{payload, path, err}
@@ -425,7 +454,7 @@ func (c *Client) post(path string, payload any) (*http.Response, error) {
}
// putDecode sends a PUT request and unmarshals the response.
-func (c *Client) putDecode(path string, payload any, v any) error {
+func (c *client) putDecode(path string, payload any, v any) error {
body, err := json.Marshal(payload)
if err != nil {
return errEncReq{payload, path, err}
@@ -453,7 +482,7 @@ func (c *Client) putDecode(path string, payload any, v any) error {
return decodeResponse(resp, v)
}
-func (c *Client) url(path string) (string, error) {
+func (c *client) url(path string) (string, error) {
return url.JoinPath(c.apiUrl, path)
}