From 2ddfc3069a2166c163561eaff96c4037296868fc Mon Sep 17 00:00:00 2001 From: codegirl-007 Date: Sat, 30 May 2026 01:03:36 -0700 Subject: [PATCH] add qbo client scaffold --- internal/qbo/client/client.go | 11 +++++++++++ internal/qbo/client/config.go | 27 ++++++++++++++++++++++++++ internal/qbo/client/errors.go | 32 +++++++++++++++++++++++++++++++ internal/qbo/client/pagination.go | 9 +++++++++ internal/qbo/client/retry.go | 19 ++++++++++++++++++ internal/qbo/tokens/source.go | 10 ++++++++++ 6 files changed, 108 insertions(+) create mode 100644 internal/qbo/client/client.go create mode 100644 internal/qbo/client/config.go create mode 100644 internal/qbo/client/errors.go create mode 100644 internal/qbo/client/pagination.go create mode 100644 internal/qbo/client/retry.go create mode 100644 internal/qbo/tokens/source.go diff --git a/internal/qbo/client/client.go b/internal/qbo/client/client.go new file mode 100644 index 0000000..69e17b8 --- /dev/null +++ b/internal/qbo/client/client.go @@ -0,0 +1,11 @@ +package client + +// Client will hold HTTP behavior for QBO requests. +type Client struct { + cfg Config +} + +// New constructs a Client with the provided configuration. +func New(cfg Config) *Client { + return &Client{cfg: cfg} +} diff --git a/internal/qbo/client/config.go b/internal/qbo/client/config.go new file mode 100644 index 0000000..6302ced --- /dev/null +++ b/internal/qbo/client/config.go @@ -0,0 +1,27 @@ +// Package client provides a minimal QuickBooks Online HTTP client scaffold. +package client + +import "net/http" + +// TokenSource supplies bearer tokens for authenticated QBO requests. +type TokenSource interface { + AccessToken() (string, error) +} + +// Config holds construction parameters for the QBO client. +type Config struct { + // BaseURL is the QBO company base URL (sandbox or production). + BaseURL string + // RealmID identifies the QuickBooks company. + RealmID string + // MinorVersion sets the optional Intuit minorversion query parameter. + MinorVersion int + // HTTPClient is the transport; if nil, http.DefaultClient is used. + HTTPClient *http.Client + // TokenSource provides bearer tokens for requests. + TokenSource TokenSource + // RetryPolicy controls retry behavior for transient errors. + RetryPolicy RetryPolicy + // UserAgent is sent on outbound requests. + UserAgent string +} diff --git a/internal/qbo/client/errors.go b/internal/qbo/client/errors.go new file mode 100644 index 0000000..9d54f60 --- /dev/null +++ b/internal/qbo/client/errors.go @@ -0,0 +1,32 @@ +package client + +import "fmt" + +// ErrUnauthorized indicates the request was not authorized (e.g., token expired). +var ErrUnauthorized = fmt.Errorf("unauthorized") + +// ErrRateLimited indicates the request hit a QBO rate limit. +var ErrRateLimited = fmt.Errorf("rate limited") + +// ErrNotFound indicates the requested resource was not found. +var ErrNotFound = fmt.Errorf("not found") + +// APIError wraps a QBO HTTP response with useful metadata. +type APIError struct { + StatusCode int // HTTP status code returned by QBO. + IntuitTID string // Intuit request ID header for tracing. + Fault []byte // Raw fault payload if provided. + Body []byte // Raw response body for debugging. + Err error // Underlying error, if any. +} + +func (e *APIError) Error() string { + if e.Err != nil { + return e.Err.Error() + } + return fmt.Sprintf("qbo api error status=%d", e.StatusCode) +} + +func (e *APIError) Unwrap() error { + return e.Err +} diff --git a/internal/qbo/client/pagination.go b/internal/qbo/client/pagination.go new file mode 100644 index 0000000..f4f4694 --- /dev/null +++ b/internal/qbo/client/pagination.go @@ -0,0 +1,9 @@ +package client + +// Page represents a single paginated response payload. +type Page struct { + StartPosition int + MaxResults int + TotalCount int + Entities map[string]any +} diff --git a/internal/qbo/client/retry.go b/internal/qbo/client/retry.go new file mode 100644 index 0000000..c2864be --- /dev/null +++ b/internal/qbo/client/retry.go @@ -0,0 +1,19 @@ +package client + +import "time" + +// RetryPolicy defines retry behavior for transient failures. +type RetryPolicy struct { + MaxAttempts int + BaseDelay time.Duration + MaxDelay time.Duration + JitterPercent float64 +} + +// DefaultRetryPolicy provides conservative defaults for QBO. +var DefaultRetryPolicy = RetryPolicy{ + MaxAttempts: 3, + BaseDelay: 500 * time.Millisecond, + MaxDelay: 30 * time.Second, + JitterPercent: 0.2, +} diff --git a/internal/qbo/tokens/source.go b/internal/qbo/tokens/source.go new file mode 100644 index 0000000..234d699 --- /dev/null +++ b/internal/qbo/tokens/source.go @@ -0,0 +1,10 @@ +// Package tokens provides token persistence and adapters for QBO clients. +package tokens + +// Source is a placeholder adapter that will wrap Service for refresh-aware tokens. +type Source struct{} + +// AccessToken is a stub implementation to satisfy the interface scaffold. +func (s *Source) AccessToken() (string, error) { + return "", nil +}