@profplum700/etsy-v3-api-client
Version:
JavaScript/TypeScript client for the Etsy Open API v3 with OAuth 2.0 authentication
505 lines (495 loc) • 16.5 kB
TypeScript
interface EtsyClientConfig {
keystring: string;
accessToken: string;
refreshToken: string;
expiresAt: Date;
refreshSave?: (_accessToken: string, _refreshToken: string, _expiresAt: Date) => void;
baseUrl?: string;
rateLimiting?: {
enabled: boolean;
maxRequestsPerDay?: number;
maxRequestsPerSecond?: number;
minRequestInterval?: number;
};
caching?: {
enabled: boolean;
ttl?: number;
storage?: CacheStorage;
};
}
interface AuthHelperConfig {
keystring: string;
redirectUri: string;
scopes: string[];
codeVerifier?: string;
state?: string;
}
interface EtsyTokens {
access_token: string;
refresh_token: string;
expires_at: Date;
token_type: string;
scope: string;
}
interface EtsyTokenResponse {
access_token: string;
token_type: string;
expires_in: number;
refresh_token: string;
scope: string;
}
type TokenRefreshCallback = (_accessToken: string, _refreshToken: string, _expiresAt: Date) => void;
interface TokenStorage {
save(_tokens: EtsyTokens): Promise<void>;
load(): Promise<EtsyTokens | null>;
clear(): Promise<void>;
}
interface EtsyApiResponse<T> {
count: number;
results: T[];
}
interface EtsyUser {
user_id: number;
shop_id?: number;
login_name?: string;
primary_email?: string;
first_name?: string;
last_name?: string;
create_timestamp?: number;
created_timestamp?: number;
bio?: string;
gender?: string;
birth_month?: string;
birth_day?: string;
birth_year?: string;
join_tsz?: number;
city?: string;
country_id?: number;
region?: string;
image_url_75x75?: string;
num_favorers?: number;
}
interface EtsyShop {
shop_id: number;
shop_name: string;
user_id: number;
create_date: number;
title?: string;
announcement?: string;
currency_code: string;
is_vacation: boolean;
vacation_message?: string;
sale_message?: string;
digital_sale_message?: string;
last_updated_tsz: number;
listing_active_count: number;
digital_listing_count: number;
login_name: string;
accepts_custom_requests: boolean;
policy_welcome?: string;
policy_payment?: string;
policy_shipping?: string;
policy_refunds?: string;
policy_additional?: string;
policy_seller_info?: string;
policy_updated_tsz?: number;
policy_has_private_receipt_info: boolean;
has_unstructured_policies: boolean;
policy_privacy?: string;
vacation_autoreply?: string;
url: string;
image_url_760x100?: string;
num_favorers: number;
languages: string[];
upcoming_local_event_id?: number;
icon_url_fullxfull?: string;
is_using_structured_policies: boolean;
has_onboarded_structured_policies: boolean;
include_dispute_form_link: boolean;
is_direct_checkout_onboarded: boolean;
is_calculated_eligible: boolean;
is_opted_in_to_buyer_promise: boolean;
is_shop_us_based: boolean;
transaction_sold_count: number;
shipping_from_country_iso: string;
shop_location_country_iso: string;
review_count: number;
review_average: number;
}
interface EtsyShopSection {
shop_section_id: number;
title: string;
rank: number;
user_id: number;
active_listing_count: number;
}
interface EtsyListing {
listing_id: number;
title: string;
description?: string;
price: {
amount: number;
divisor: number;
currency_code: string;
};
url: string;
images?: Array<{
url_570xN: string;
alt_text?: string;
}>;
when_made?: string;
shop_section_id?: number;
tags?: string[];
materials?: string[];
style?: string[];
item_length?: number;
item_width?: number;
item_height?: number;
item_dimensions_unit?: string;
state?: 'active' | 'inactive' | 'draft' | 'expired';
creation_tsz?: number;
ending_tsz?: number;
original_creation_tsz?: number;
last_modified_tsz?: number;
views?: number;
num_favorers?: number;
shop_id?: number;
user_id?: number;
category_id?: number;
is_supply?: boolean;
is_private?: boolean;
recipient?: string;
occasion?: string;
style_id?: number[];
non_taxable?: boolean;
is_customizable?: boolean;
is_digital?: boolean;
file_data?: string;
can_write_inventory?: boolean;
has_variations?: boolean;
should_auto_renew?: boolean;
language?: string;
processing_min?: number;
processing_max?: number;
who_made?: string;
is_mass_produced?: boolean;
item_weight?: number;
item_weight_unit?: string;
shipping_template_id?: number;
featured_rank?: number;
skus?: string[];
used_manufacturer?: boolean;
}
interface EtsyListingImage {
listing_image_id: number;
hex_code?: string;
red?: number;
green?: number;
blue?: number;
hue?: number;
saturation?: number;
brightness?: number;
is_black_and_white?: boolean;
creation_tsz?: number;
listing_id?: number;
rank?: number;
url_75x75?: string;
url_170x135?: string;
url_570xN?: string;
url_fullxfull?: string;
full_height?: number;
full_width?: number;
alt_text?: string;
}
interface EtsyListingInventory {
products: EtsyListingProduct[];
price_on_property?: number[];
quantity_on_property?: number[];
sku_on_property?: number[];
}
interface EtsyListingProduct {
product_id: number;
sku?: string;
is_deleted?: boolean;
offerings: EtsyListingOffering[];
property_values?: EtsyListingPropertyValue[];
}
interface EtsyListingOffering {
offering_id: number;
price: {
amount: number;
divisor: number;
currency_code: string;
};
quantity: number;
is_enabled: boolean;
is_deleted: boolean;
}
interface EtsyListingPropertyValue {
property_id: number;
property_name: string;
scale_id?: number;
scale_name?: string;
value_ids?: number[];
values?: string[];
}
interface EtsySellerTaxonomyNode {
id: number;
level: number;
name: string;
parent_id: number | null;
children: EtsySellerTaxonomyNode[];
full_path_taxonomy_ids: number[];
}
interface ListingParams {
limit?: number;
offset?: number;
state?: 'active' | 'inactive' | 'draft' | 'expired';
sort_on?: 'created' | 'ending' | 'price' | 'views' | 'score';
sort_order?: 'up' | 'down';
includes?: string[];
}
interface SearchParams {
keywords?: string;
category?: string;
limit?: number;
offset?: number;
sort_on?: 'created' | 'price' | 'score';
sort_order?: 'up' | 'down';
min_price?: number;
max_price?: number;
tags?: string[];
location?: string;
shop_location?: string;
}
interface RateLimitConfig {
maxRequestsPerDay: number;
maxRequestsPerSecond: number;
minRequestInterval: number;
}
interface RateLimitStatus {
remainingRequests: number;
resetTime: Date;
canMakeRequest: boolean;
}
declare class EtsyApiError extends Error {
_statusCode?: number | undefined;
_response?: unknown | undefined;
constructor(message: string, _statusCode?: number | undefined, _response?: unknown | undefined);
get statusCode(): number | undefined;
get response(): unknown | undefined;
}
declare class EtsyAuthError extends Error {
_code?: string | undefined;
constructor(message: string, _code?: string | undefined);
get code(): string | undefined;
}
declare class EtsyRateLimitError extends Error {
_retryAfter?: number | undefined;
constructor(message: string, _retryAfter?: number | undefined);
get retryAfter(): number | undefined;
}
interface CacheStorage {
get(_key: string): Promise<string | null>;
set(_key: string, _value: string, _ttl?: number): Promise<void>;
delete(_key: string): Promise<void>;
clear(): Promise<void>;
}
interface LoggerInterface {
debug(_message: string, ..._args: unknown[]): void;
info(_message: string, ..._args: unknown[]): void;
warn(_message: string, ..._args: unknown[]): void;
error(_message: string, ..._args: unknown[]): void;
}
declare class EtsyClient {
private tokenManager;
private rateLimiter;
private baseUrl;
private logger;
private cache?;
private cacheTtl;
private keystring;
constructor(config: EtsyClientConfig);
private makeRequest;
private getApiKey;
getUser(): Promise<EtsyUser>;
getShop(shopId?: string): Promise<EtsyShop>;
getShopByOwnerUserId(userId: string): Promise<EtsyShop>;
getShopSections(shopId?: string): Promise<EtsyShopSection[]>;
getShopSection(shopId: string, sectionId: string): Promise<EtsyShopSection>;
getListingsByShop(shopId?: string, params?: ListingParams): Promise<EtsyListing[]>;
getListing(listingId: string, includes?: string[]): Promise<EtsyListing>;
findAllListingsActive(params?: SearchParams): Promise<EtsyListing[]>;
getListingImages(listingId: string): Promise<EtsyListingImage[]>;
getListingInventory(listingId: string): Promise<EtsyListingInventory>;
getSellerTaxonomyNodes(): Promise<EtsySellerTaxonomyNode[]>;
getUserShops(): Promise<EtsyShop[]>;
getRemainingRequests(): number;
getRateLimitStatus(): RateLimitStatus;
clearCache(): Promise<void>;
getCurrentTokens(): EtsyTokens | null;
isTokenExpired(): boolean;
refreshToken(): Promise<EtsyTokens>;
private fetch;
}
declare class AuthHelper {
private readonly keystring;
private readonly redirectUri;
private readonly scopes;
private codeVerifier;
private state;
private authorizationCode?;
private receivedState?;
private initialized;
constructor(config: AuthHelperConfig);
private initialize;
getAuthUrl(): Promise<string>;
setAuthorizationCode(code: string, state: string): Promise<void>;
getAccessToken(): Promise<EtsyTokens>;
getState(): Promise<string>;
getCodeVerifier(): Promise<string>;
getScopes(): string[];
getRedirectUri(): string;
}
declare const ETSY_SCOPES: {
readonly LISTINGS_READ: "listings_r";
readonly SHOPS_READ: "shops_r";
readonly PROFILE_READ: "profile_r";
readonly FAVORITES_READ: "favorites_r";
readonly FEEDBACK_READ: "feedback_r";
readonly TREASURY_READ: "treasury_r";
readonly LISTINGS_WRITE: "listings_w";
readonly SHOPS_WRITE: "shops_w";
readonly PROFILE_WRITE: "profile_w";
readonly FAVORITES_WRITE: "favorites_w";
readonly FEEDBACK_WRITE: "feedback_w";
readonly TREASURY_WRITE: "treasury_w";
readonly LISTINGS_DELETE: "listings_d";
readonly SHOPS_DELETE: "shops_d";
readonly PROFILE_DELETE: "profile_d";
readonly FAVORITES_DELETE: "favorites_d";
readonly FEEDBACK_DELETE: "feedback_d";
readonly TREASURY_DELETE: "treasury_d";
readonly TRANSACTIONS_READ: "transactions_r";
readonly TRANSACTIONS_WRITE: "transactions_w";
readonly BILLING_READ: "billing_r";
readonly CART_READ: "cart_r";
readonly CART_WRITE: "cart_w";
readonly RECOMMEND_READ: "recommend_r";
readonly RECOMMEND_WRITE: "recommend_w";
readonly ADDRESS_READ: "address_r";
readonly ADDRESS_WRITE: "address_w";
readonly EMAIL_READ: "email_r";
};
declare const COMMON_SCOPE_COMBINATIONS: {
readonly SHOP_READ_ONLY: readonly ["shops_r", "listings_r", "profile_r"];
readonly SHOP_MANAGEMENT: readonly ["shops_r", "shops_w", "listings_r", "listings_w", "listings_d", "profile_r", "transactions_r"];
readonly BASIC_ACCESS: readonly ["shops_r", "listings_r"];
};
declare class MemoryTokenStorage implements TokenStorage {
private tokens;
save(tokens: EtsyTokens): Promise<void>;
load(): Promise<EtsyTokens | null>;
clear(): Promise<void>;
}
declare class TokenManager {
private keystring;
private currentTokens;
private refreshCallback?;
private storage?;
private refreshPromise?;
constructor(config: EtsyClientConfig, storage?: TokenStorage);
getAccessToken(): Promise<string>;
refreshToken(): Promise<EtsyTokens>;
private performTokenRefresh;
getCurrentTokens(): EtsyTokens | null;
updateTokens(tokens: EtsyTokens): void;
isTokenExpired(): boolean;
willTokenExpireSoon(minutes?: number): boolean;
clearTokens(): Promise<void>;
getTimeUntilExpiration(): number | null;
private fetch;
}
declare function createDefaultTokenStorage(options?: {
filePath?: string;
storageKey?: string;
preferSession?: boolean;
}): TokenStorage;
declare class LocalStorageTokenStorage implements TokenStorage {
private storageKey;
constructor(storageKey?: string);
save(tokens: EtsyTokens): Promise<void>;
load(): Promise<EtsyTokens | null>;
clear(): Promise<void>;
}
declare class SessionStorageTokenStorage implements TokenStorage {
private storageKey;
constructor(storageKey?: string);
save(tokens: EtsyTokens): Promise<void>;
load(): Promise<EtsyTokens | null>;
clear(): Promise<void>;
}
declare class FileTokenStorage implements TokenStorage {
private filePath;
constructor(filePath: string);
save(tokens: EtsyTokens): Promise<void>;
load(): Promise<EtsyTokens | null>;
clear(): Promise<void>;
private _writeFile;
private _readFile;
private _deleteFile;
}
declare class EtsyRateLimiter {
private requestCount;
private dailyReset;
private lastRequestTime;
private readonly config;
constructor(config?: Partial<RateLimitConfig>);
private setNextDailyReset;
waitForRateLimit(): Promise<void>;
getRateLimitStatus(): RateLimitStatus;
getRemainingRequests(): number;
reset(): void;
canMakeRequest(): boolean;
getTimeUntilNextRequest(): number;
getConfig(): RateLimitConfig;
}
declare const defaultRateLimiter: EtsyRateLimiter;
declare const isBrowser: boolean;
declare const isNode: boolean;
declare const hasLocalStorage: boolean;
declare const hasSessionStorage: boolean;
declare function getEnvironmentInfo(): {
isBrowser: boolean;
isNode: boolean;
isWebWorker: boolean;
hasFetch: boolean;
hasWebCrypto: boolean;
hasLocalStorage: boolean;
hasSessionStorage: boolean;
userAgent: string;
nodeVersion?: string;
};
declare function getAvailableStorage(): 'localStorage' | 'sessionStorage' | 'memory' | 'file';
declare function generateRandomBase64Url(length: number): Promise<string>;
declare function sha256(data: string | Uint8Array): Promise<Uint8Array>;
declare function sha256Base64Url(data: string | Uint8Array): Promise<string>;
declare function generateCodeVerifier(): Promise<string>;
declare function generateState(): Promise<string>;
declare function createCodeChallenge(codeVerifier: string): Promise<string>;
declare function createEtsyClient(config: EtsyClientConfig): EtsyClient;
declare function createAuthHelper(config: AuthHelperConfig): AuthHelper;
declare function createTokenManager(config: EtsyClientConfig, storage?: TokenStorage): TokenManager;
declare function createRateLimiter(config?: Partial<RateLimitConfig>): EtsyRateLimiter;
declare const VERSION = "1.0.2";
declare const LIBRARY_NAME = "etsy-v3-api-client";
declare function getLibraryInfo(): {
name: string;
version: string;
description: string;
author: string;
license: string;
homepage: string;
};
export { AuthHelper, COMMON_SCOPE_COMBINATIONS, ETSY_SCOPES, EtsyApiError, EtsyAuthError, EtsyClient, EtsyRateLimitError, EtsyRateLimiter, FileTokenStorage, LIBRARY_NAME, LocalStorageTokenStorage, MemoryTokenStorage, SessionStorageTokenStorage, TokenManager, VERSION, createAuthHelper, createCodeChallenge, createDefaultTokenStorage, createEtsyClient, createRateLimiter, createTokenManager, EtsyClient as default, defaultRateLimiter, generateCodeVerifier, generateRandomBase64Url, generateState, getAvailableStorage, getEnvironmentInfo, getLibraryInfo, hasLocalStorage, hasSessionStorage, isBrowser, isNode, sha256, sha256Base64Url };
export type { AuthHelperConfig, CacheStorage, EtsyApiResponse, EtsyClientConfig, EtsyListing, EtsyListingImage, EtsyListingInventory, EtsyListingOffering, EtsyListingProduct, EtsyListingPropertyValue, EtsySellerTaxonomyNode, EtsyShop, EtsyShopSection, EtsyTokenResponse, EtsyTokens, EtsyUser, ListingParams, LoggerInterface, RateLimitConfig, RateLimitStatus, SearchParams, TokenRefreshCallback, TokenStorage };