Documentation
¶
Overview ¶
Package shop defines the core interfaces and types for a multi-platform shopping CLI. Providers implement these interfaces; the CLI consumes them.
Index ¶
- Variables
- func ExitCode(err error) int
- func IsAuthExpired(err error) bool
- func IsAuthRequired(err error) bool
- func IsCartChanged(err error) bool
- func IsNotFound(err error) bool
- func IsNotSupported(err error) bool
- func IsRateLimited(err error) bool
- func IsStoreNotFound(err error) bool
- func Register(p Provider)
- func SetResolver(fn func(ctx context.Context, storeValue string) (Store, error))
- type AccountInfo
- type Address
- type Availability
- type AvailabilityStatus
- type Capabilities
- type Cart
- type CartContents
- type CartEntry
- type Challenge
- type CheckoutOpts
- type CheckoutResult
- type DetectCost
- type Error
- type ErrorCode
- type Image
- type LoginResult
- type Money
- type Offer
- type OfferCondition
- type OffersQuery
- type OffersResult
- type Order
- type PaymentMethod
- type Product
- type ProductSummary
- type Provider
- type Rating
- type RegistryEntry
- type Review
- type ReviewSort
- type ReviewsQuery
- type ReviewsResult
- type SearchFilter
- type SearchFilterOption
- type SearchQuery
- type SearchResult
- type SearchSort
- type Seller
- type ShippingInfo
- type ShippingOption
- type Spec
- type StarBreakdown
- type Store
- type StoreInfo
- type VariantCombo
- type VariantDimension
- type VariantInfo
- type VariantOption
- type VariantsResult
Constants ¶
This section is empty.
Variables ¶
var ExitCodes = map[ErrorCode]int{ ErrAuthRequired: 10, ErrAuthExpired: 11, ErrAuthFailed: 12, ErrAuthTimeout: 13, ErrStoreNotFound: 20, ErrNotSupported: 21, ErrNotFound: 30, ErrOutOfStock: 31, ErrCartEmpty: 40, ErrCartChanged: 41, ErrQuantityLimit: 42, ErrRateLimited: 50, ErrStoreError: 51, ErrNetwork: 60, ErrInvalidInput: 2, ErrConfigError: 3, ErrInternal: 1, }
ExitCodes maps error codes to CLI exit codes.
var SkillMD string
SkillMD is the embedded SKILL.md content for use with AI agents.
Functions ¶
func ExitCode ¶
ExitCode returns the CLI exit code for the given error. Returns 1 for unknown errors.
func IsAuthExpired ¶
IsAuthExpired reports whether err is an auth_expired error.
func IsAuthRequired ¶
IsAuthRequired reports whether err is an auth_required error.
func IsCartChanged ¶
IsCartChanged reports whether err is a cart_changed error.
func IsNotFound ¶
IsNotFound reports whether err is a not_found error.
func IsNotSupported ¶
IsNotSupported reports whether err is a not_supported error.
func IsRateLimited ¶
IsRateLimited reports whether err is a rate_limited error.
func IsStoreNotFound ¶
IsStoreNotFound reports whether err is a store_not_found error.
Types ¶
type AccountInfo ¶
type AccountInfo struct {
Authenticated bool `json:"authenticated"`
AccountID string `json:"accountId,omitempty"`
AccountName string `json:"accountName,omitempty"`
Email string `json:"email,omitempty"`
ExpiresAt string `json:"expiresAt,omitempty"`
}
AccountInfo is returned by Store.WhoAmI() and LoginResult.
type Address ¶
type Address struct {
ID string `json:"id"`
Label string `json:"label,omitempty"`
Name string `json:"name"`
Line1 string `json:"line1"`
Line2 string `json:"line2,omitempty"`
City string `json:"city"`
State string `json:"state,omitempty"`
PostalCode string `json:"postalCode"`
Country string `json:"country"`
Phone string `json:"phone,omitempty"`
IsDefault bool `json:"isDefault"`
}
Address is a shipping/billing address.
type Availability ¶
type Availability struct {
Status AvailabilityStatus `json:"status"`
Message string `json:"message,omitempty"`
}
Availability represents whether a product can be purchased.
type AvailabilityStatus ¶
type AvailabilityStatus string
AvailabilityStatus is the purchase-readiness of a product.
const ( AvailabilityInStock AvailabilityStatus = "in_stock" AvailabilityLowStock AvailabilityStatus = "low_stock" AvailabilityOutOfStock AvailabilityStatus = "out_of_stock" AvailabilityPreorder AvailabilityStatus = "preorder" )
type Capabilities ¶
type Capabilities struct {
Search bool `json:"search"`
Reviews bool `json:"reviews"`
Offers bool `json:"offers"`
Variants bool `json:"variants"`
Cart bool `json:"cart"`
Checkout bool `json:"checkout"`
Addresses bool `json:"addresses"`
PaymentMethods bool `json:"paymentMethods"`
ShippingOptions bool `json:"shippingOptions"`
Coupons bool `json:"coupons"`
}
Capabilities declares which optional features a store implementation supports.
type Cart ¶
type Cart interface {
// Add adds a product to the cart. quantity must be >= 1.
Add(ctx context.Context, id string, quantity int) (*CartContents, error)
// Remove removes a product entirely from the cart.
Remove(ctx context.Context, id string) (*CartContents, error)
// View returns the current cart snapshot.
View(ctx context.Context) (*CartContents, error)
// Clear empties the cart.
Clear(ctx context.Context) (*CartContents, error)
}
Cart manages line items for a single store. Cart state is internal to the provider implementation — the CLI only reads it via View().
type CartContents ¶
CartContents is a snapshot of the current cart state.
type Challenge ¶
type Challenge struct {
URL string `json:"url"`
Code string `json:"code,omitempty"`
ExpiresAt string `json:"expiresAt,omitempty"`
Message string `json:"message,omitempty"`
}
Challenge describes an external action the consumer must complete to finish authentication.
type CheckoutOpts ¶
type CheckoutOpts struct {
AddressID string `json:"addressId,omitempty"`
PaymentMethodID string `json:"paymentMethodId,omitempty"`
ShippingOption string `json:"shippingOption,omitempty"`
CouponCode string `json:"couponCode,omitempty"`
}
CheckoutOpts controls checkout preview behavior.
type CheckoutResult ¶
type CheckoutResult struct {
CheckoutID string `json:"checkoutId"`
Items []CartEntry `json:"items"`
Subtotal Money `json:"subtotal"`
Shipping Money `json:"shipping"`
Tax Money `json:"tax"`
Discount Money `json:"discount"`
Total Money `json:"total"`
ShippingAddress *Address `json:"shippingAddress,omitempty"`
PaymentMethod *PaymentMethod `json:"paymentMethod,omitempty"`
ShippingOptions []ShippingOption `json:"shippingOptions,omitempty"`
SelectedShipping *ShippingOption `json:"selectedShipping,omitempty"`
EstimatedDelivery string `json:"estimatedDelivery,omitempty"`
Warnings []string `json:"warnings,omitempty"`
Attributes map[string]any `json:"attributes,omitempty"`
}
CheckoutResult is the order preview returned by Store.Checkout().
type DetectCost ¶
type DetectCost int
DetectCost indicates how expensive a provider's Detect call is.
const ( // DetectCostFree is a pure string match, no network. DetectCostFree DetectCost = 0 // DetectCostCheap is a single HTTP request. DetectCostCheap DetectCost = 1 // DetectCostModerate is multiple requests or DNS probes. DetectCostModerate DetectCost = 2 )
type Error ¶
type Error struct {
Code ErrorCode `json:"code"`
Message string `json:"message"`
Details map[string]any `json:"details,omitempty"`
}
Error is the structured error type. Every error from every provider gets normalized into this shape before the CLI outputs it.
func NotImplemented ¶
NotImplemented returns a standard not-supported error for the given provider and operation. Shared across all provider stubs.
type ErrorCode ¶
type ErrorCode string
ErrorCode identifies the category of an error.
const ( // Auth errors. ErrAuthRequired ErrorCode = "auth_required" ErrAuthExpired ErrorCode = "auth_expired" ErrAuthFailed ErrorCode = "auth_failed" ErrAuthTimeout ErrorCode = "auth_timeout" // Product/search errors. ErrNotFound ErrorCode = "not_found" ErrOutOfStock ErrorCode = "out_of_stock" // Cart errors. ErrCartEmpty ErrorCode = "cart_empty" ErrCartChanged ErrorCode = "cart_changed" ErrQuantityLimit ErrorCode = "quantity_limit" // Store errors. ErrStoreNotFound ErrorCode = "store_not_found" ErrNotSupported ErrorCode = "not_supported" ErrRateLimited ErrorCode = "rate_limited" ErrStoreError ErrorCode = "store_error" // Input errors. ErrInvalidInput ErrorCode = "invalid_input" // System errors. ErrInternal ErrorCode = "internal" ErrNetwork ErrorCode = "network" ErrConfigError ErrorCode = "config_error" )
type Image ¶
type Image struct {
URL string `json:"url"`
Alt string `json:"alt,omitempty"`
Width int `json:"width,omitempty"`
Height int `json:"height,omitempty"`
}
Image is a product image with optional dimensions.
type LoginResult ¶
type LoginResult struct {
Authenticated bool `json:"authenticated"`
Account *AccountInfo `json:"account,omitempty"`
Challenge *Challenge `json:"challenge,omitempty"`
}
LoginResult is returned by Store.Login().
type Money ¶
Money represents a monetary value in minor units (cents for USD, pence for GBP, etc.). Never a float.
type Offer ¶
type Offer struct {
ID string `json:"id"`
Seller Seller `json:"seller"`
Condition OfferCondition `json:"condition"`
Price Money `json:"price"`
Shipping *ShippingInfo `json:"shipping,omitempty"`
Availability Availability `json:"availability"`
IsBuyBox bool `json:"isBuyBox,omitempty"`
IsPrime bool `json:"isPrime,omitempty"`
DeliveryDate string `json:"deliveryDate,omitempty"`
Attributes map[string]any `json:"attributes,omitempty"`
}
Offer represents a single seller's listing for a product.
type OfferCondition ¶
type OfferCondition string
OfferCondition filters offers by item condition.
const ( ConditionAny OfferCondition = "" ConditionNew OfferCondition = "new" ConditionUsedLikeNew OfferCondition = "used_like_new" ConditionUsedGood OfferCondition = "used_good" ConditionUsedFair OfferCondition = "used_fair" ConditionRefurbished OfferCondition = "refurbished" )
type OffersQuery ¶
type OffersQuery struct {
Condition OfferCondition `json:"condition,omitempty"`
Page int `json:"page,omitempty"`
PageSize int `json:"pageSize,omitempty"`
}
OffersQuery controls offer listing.
type OffersResult ¶
type OffersResult struct {
Offers []Offer `json:"offers"`
Page int `json:"page"`
HasMore bool `json:"hasMore"`
}
OffersResult is a paginated list of offers for a product.
type Order ¶
type Order struct {
OrderID string `json:"orderId"`
Status string `json:"status"`
Items []CartEntry `json:"items"`
Total Money `json:"total"`
ShippingAddress *Address `json:"shippingAddress,omitempty"`
PaymentMethod *PaymentMethod `json:"paymentMethod,omitempty"`
EstimatedDelivery string `json:"estimatedDelivery,omitempty"`
PlacedAt string `json:"placedAt"`
Attributes map[string]any `json:"attributes,omitempty"`
}
Order is the result of a successfully placed order.
type PaymentMethod ¶
type PaymentMethod struct {
ID string `json:"id"`
Type string `json:"type"`
Label string `json:"label"`
Last4 string `json:"last4,omitempty"`
ExpMonth int `json:"expMonth,omitempty"`
ExpYear int `json:"expYear,omitempty"`
IsDefault bool `json:"isDefault"`
}
PaymentMethod is a saved payment instrument. Sensitive details are masked.
type Product ¶
type Product struct {
ID string `json:"id"`
Title string `json:"title"`
Brand string `json:"brand,omitempty"`
Description string `json:"description,omitempty"`
URL string `json:"url"`
Images []Image `json:"images"`
Price *Money `json:"price,omitempty"`
ListPrice *Money `json:"listPrice,omitempty"`
Rating *Rating `json:"rating,omitempty"`
Availability Availability `json:"availability"`
Seller *Seller `json:"seller,omitempty"`
Categories []string `json:"categories,omitempty"`
Features []string `json:"features,omitempty"`
Specs []Spec `json:"specs,omitempty"`
VariantInfo *VariantInfo `json:"variantInfo,omitempty"`
Attributes map[string]any `json:"attributes,omitempty"`
}
Product is the full representation of a product.
type ProductSummary ¶
type ProductSummary struct {
ID string `json:"id"`
Title string `json:"title"`
Brand string `json:"brand,omitempty"`
URL string `json:"url"`
ImageURL string `json:"imageUrl,omitempty"`
Price *Money `json:"price,omitempty"`
ListPrice *Money `json:"listPrice,omitempty"`
Rating *Rating `json:"rating,omitempty"`
Availability Availability `json:"availability"`
Sponsored bool `json:"sponsored,omitempty"`
Badge string `json:"badge,omitempty"`
Attributes map[string]any `json:"attributes,omitempty"`
}
ProductSummary is the condensed representation returned in search results.
type Provider ¶
type Provider interface {
// Name returns the provider's unique identifier (e.g., "amazon").
Name() string
// Detect probes a handle/domain and returns true if this provider can
// handle it. Called during auto-discovery for unknown domains.
// Implementations should be fast and not require auth. Returns a
// StoreInfo if detected, which gets cached in the registry.
Detect(ctx context.Context, handle string) (*StoreInfo, error)
// DetectCost indicates how expensive Detect is, allowing the resolution
// layer to sort providers optimally (cheapest first).
DetectCost() DetectCost
// Store creates a Store instance for the given handle. The handle is
// the canonical domain for the store. configDir is the path to the
// CLI's config directory (e.g., ~/.config/shop) for auth file I/O.
Store(ctx context.Context, handle string, configDir string) (Store, error)
}
Provider is a factory that creates Store instances for compatible domains. Each provider handles a family of stores (e.g., "amazon" handles amazon.com/co.uk/etc.).
type Rating ¶
type Rating struct {
Average float64 `json:"average"`
Count int `json:"count"`
Stars *StarBreakdown `json:"stars,omitempty"`
}
Rating is the aggregate customer rating for a product.
type RegistryEntry ¶
type RegistryEntry struct {
Alias string `json:"alias"`
Domain string `json:"domain"`
Provider string `json:"provider"`
Name string `json:"name"`
Country string `json:"country,omitempty"`
Currency string `json:"currency,omitempty"`
BuiltIn bool `json:"builtIn"`
DetectedAt string `json:"detectedAt,omitempty"`
DetectedBy string `json:"detectedBy,omitempty"`
ProviderConfig map[string]any `json:"providerConfig,omitempty"`
}
RegistryEntry is a single known store in the persistent registry.
type Review ¶
type Review struct {
ID string `json:"id"`
Author string `json:"author"`
Title string `json:"title,omitempty"`
Body string `json:"body"`
Rating int `json:"rating"`
Date string `json:"date"`
Verified bool `json:"verified"`
Helpful int `json:"helpful,omitempty"`
Images []Image `json:"images,omitempty"`
Attributes map[string]any `json:"attributes,omitempty"`
}
Review is a single customer review.
type ReviewSort ¶
type ReviewSort string
ReviewSort controls the ordering of reviews.
const ( ReviewSortRecent ReviewSort = "recent" ReviewSortHelpful ReviewSort = "helpful" ReviewSortRating ReviewSort = "rating" )
type ReviewsQuery ¶
type ReviewsQuery struct {
Page int `json:"page,omitempty"`
PageSize int `json:"pageSize,omitempty"`
Sort ReviewSort `json:"sort,omitempty"`
Rating *int `json:"rating,omitempty"`
}
ReviewsQuery controls review pagination and filtering.
type ReviewsResult ¶
type ReviewsResult struct {
Rating Rating `json:"rating"`
Reviews []Review `json:"reviews"`
Page int `json:"page"`
HasMore bool `json:"hasMore"`
}
ReviewsResult is a paginated list of reviews with aggregate stats.
type SearchFilter ¶
type SearchFilter struct {
Name string `json:"name"`
Key string `json:"key"`
Options []SearchFilterOption `json:"options"`
}
SearchFilter describes a filterable facet returned by the store (e.g., brand, department, price range).
type SearchFilterOption ¶
type SearchFilterOption struct {
Value string `json:"value"`
Label string `json:"label"`
Count int `json:"count,omitempty"`
}
SearchFilterOption is a single selectable value within a SearchFilter.
type SearchQuery ¶
type SearchQuery struct {
Query string `json:"query"`
Page int `json:"page,omitempty"`
PageSize int `json:"pageSize,omitempty"`
Sort SearchSort `json:"sort,omitempty"`
MinPrice *int64 `json:"minPrice,omitempty"`
MaxPrice *int64 `json:"maxPrice,omitempty"`
MinRating *float64 `json:"minRating,omitempty"`
Category string `json:"category,omitempty"`
Filters map[string]string `json:"filters,omitempty"`
}
SearchQuery defines what to search for and how to filter/sort results.
type SearchResult ¶
type SearchResult struct {
Products []ProductSummary `json:"products"`
Count int `json:"count"`
Page int `json:"page"`
HasMore bool `json:"hasMore"`
Filters []SearchFilter `json:"filters,omitempty"`
Warnings []string `json:"warnings,omitempty"`
}
SearchResult is a paginated list of product summaries.
type SearchSort ¶
type SearchSort string
SearchSort controls the ordering of search results.
const ( SortRelevance SearchSort = "relevance" SortPriceLow SearchSort = "price_low" SortPriceHigh SearchSort = "price_high" SortRating SearchSort = "rating" SortNewest SearchSort = "newest" SortBestSeller SearchSort = "best_seller" )
type Seller ¶
type Seller struct {
ID string `json:"id,omitempty"`
Name string `json:"name"`
URL string `json:"url,omitempty"`
}
Seller represents the merchant selling a product.
type ShippingInfo ¶
type ShippingInfo struct {
Price *Money `json:"price,omitempty"`
Description string `json:"description,omitempty"`
Speed string `json:"speed,omitempty"`
}
ShippingInfo describes shipping cost and speed for an offer.
type ShippingOption ¶
type ShippingOption struct {
ID string `json:"id"`
Label string `json:"label"`
Price Money `json:"price"`
EstimatedDays string `json:"estimatedDays,omitempty"`
EstimatedDate string `json:"estimatedDate,omitempty"`
IsDefault bool `json:"isDefault"`
}
ShippingOption is a selectable shipping speed/method during checkout.
type StarBreakdown ¶
type StarBreakdown struct {
Five float64 `json:"five"`
Four float64 `json:"four"`
Three float64 `json:"three"`
Two float64 `json:"two"`
One float64 `json:"one"`
}
StarBreakdown shows the distribution of ratings by star level. Values are percentages (0-100), not counts.
type Store ¶
type Store interface {
// Info returns metadata about this store.
Info() StoreInfo
// Login authenticates with the store. Handles the full lifecycle:
// - No existing state + no creds → starts device code/OAuth flow, returns challenge
// - No existing state + creds → authenticates directly, returns authenticated
// - Pending challenge exists → polls for completion
// - Already authenticated → returns authenticated (idempotent)
Login(ctx context.Context, creds map[string]string) (*LoginResult, error)
// Logout revokes credentials and clears stored tokens.
Logout(ctx context.Context) error
// WhoAmI returns the current auth state. Read-only — no side effects.
WhoAmI(ctx context.Context) (*AccountInfo, error)
// Search performs a product search with the given query and filters.
Search(ctx context.Context, query *SearchQuery) (*SearchResult, error)
// Product returns full details for a single product by its opaque ID.
Product(ctx context.Context, productID string) (*Product, error)
// Offers returns all available offers (sellers/conditions) for a product.
Offers(ctx context.Context, productID string, opts *OffersQuery) (*OffersResult, error)
// Reviews returns customer reviews for a product.
Reviews(ctx context.Context, productID string, opts *ReviewsQuery) (*ReviewsResult, error)
// Variants returns the full variant tree for a product.
Variants(ctx context.Context, productID string) (*VariantsResult, error)
// Cart returns the cart interface for this store. The cart is a singleton
// per store instance.
Cart() Cart
// Checkout previews the current cart as an order. Returns a full cost
// breakdown and a checkout ID (hash of cart state). Does not place the order.
Checkout(ctx context.Context, opts *CheckoutOpts) (*CheckoutResult, error)
// PlaceOrder commits the checkout. The checkoutID must match the hash
// from a prior Checkout() call — if the cart changed, this fails with
// ErrCartChanged.
PlaceOrder(ctx context.Context, checkoutID string) (*Order, error)
// Addresses returns saved shipping addresses for the authenticated account.
Addresses(ctx context.Context) ([]Address, error)
// PaymentMethods returns saved payment methods for the authenticated account.
PaymentMethods(ctx context.Context) ([]PaymentMethod, error)
// Capabilities returns which optional features this store supports.
Capabilities() Capabilities
}
Store is the primary shopping interface. All operations are scoped to a single merchant/domain. Implementations handle their own HTTP clients, auth token refresh, and platform-specific API details.
type StoreInfo ¶
type StoreInfo struct {
Name string `json:"name"`
Domain string `json:"domain"`
Provider string `json:"provider"`
Country string `json:"country,omitempty"`
Currency string `json:"currency,omitempty"`
LogoURL string `json:"logoUrl,omitempty"`
}
StoreInfo is metadata about a store.
type VariantCombo ¶
type VariantCombo struct {
Values map[string]string `json:"values"`
ProductID string `json:"productId"`
Price *Money `json:"price,omitempty"`
Available bool `json:"available"`
}
VariantCombo maps a specific set of dimension values to a product ID.
type VariantDimension ¶
type VariantDimension struct {
Name string `json:"name"`
Options []VariantOption `json:"options"`
}
VariantDimension is a single axis of variation (e.g., "Color", "Size").
type VariantInfo ¶
type VariantInfo struct {
ParentID string `json:"parentId,omitempty"`
Selected map[string]string `json:"selected,omitempty"` // e.g. {"Color": "Black"}
}
VariantInfo describes which variant this product is within its family. Use shop variants to get the full dimension/combination tree.
type VariantOption ¶
type VariantOption struct {
Value string `json:"value"`
ProductID string `json:"productId,omitempty"`
Available bool `json:"available"`
ImageURL string `json:"imageUrl,omitempty"`
}
VariantOption is a single value within a dimension.
type VariantsResult ¶
type VariantsResult struct {
ParentID string `json:"parentId"`
Dimensions []VariantDimension `json:"dimensions"`
Combinations []VariantCombo `json:"combinations"`
Truncated bool `json:"truncated,omitempty"`
}
VariantsResult is the full variant tree returned by Store.Variants().
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
cmd
|
|
|
shop
command
|
|
|
internal
|
|
|
app
Package app wires providers, config, and the store registry together.
|
Package app wires providers, config, and the store registry together. |
|
cli
Package cli defines the cobra command tree for the shop CLI.
|
Package cli defines the cobra command tree for the shop CLI. |
|
config
Package config handles loading, saving, and managing the shop CLI's persistent configuration files: config.json, registry.json, and auth state.
|
Package config handles loading, saving, and managing the shop CLI's persistent configuration files: config.json, registry.json, and auth state. |
|
provider/amazon
Package amazon implements the shop.Provider interface for Amazon stores.
|
Package amazon implements the shop.Provider interface for Amazon stores. |