infini-storefront-sdk
v1.0.5
Published
TypeScript SDK for the Eshop Storefront API
Maintainers
Readme
Eshop Storefront SDK
A fully-typed, production-ready TypeScript SDK for interacting with the Eshop Storefront API.
Installation
Since this package is part of the local workspace, you can install it in your Storefront application (e.g., Next.js) by treating it as a local dependency or by publishing it to an artifact registry.
# Using npm workspaces:
npm install @eshop/storefront-sdkInitialization
Initialize the SDK once with your store's Base URL and API Key. The init() call automatically fetches initial "bootstrap" data configuring your store (currency, settings, payment providers, delivery options), which is then available synchronously via sdk.store.
import { StorefrontSDK } from '@eshop/storefront-sdk';
export const sdk = new StorefrontSDK({
baseUrl: process.env.NEXT_PUBLIC_CORE_API_URL || 'http://localhost:3000/api',
publicApiKey: process.env.NEXT_PUBLIC_STOREFRONT_PUBLIC_API_KEY || 'pk_test_...',
// Optional: Pass an initial session ID if the user already has a guest cart
// sessionId: 'sess_12345',
// Optional: Global retry config for 5xx and Network Errors
retry: 2,
});
// Bootstrap the SDK (safe to call multiple times, requests are deduplicated)
await sdk.init();
console.log(sdk.store.store.name);
console.log(sdk.store.settings.currency);Note: Methods on individual modules (like
sdk.products,sdk.cart) do NOT require waiting forsdk.init(). Onlysdk.storerequires it.
Unified Checkout Example
The .checkout module handles the entire workflow of turning a cart into a placed order and (if required) creating a payment intent to render your payment elements (Stripe/Razorpay), all in a single call.
try {
const result = await sdk.checkout.process({
paymentProvider: 'STRIPE', // or RAZORPAY, MANUAL
couponCode: 'WELCOME10',
shippingAddress: {
street: '123 E-commerce Way',
city: 'Delhi',
postalCode: '110001'
},
deliveryMode: 'DELIVERY'
});
console.log('Order created:', result.order.orderId);
// If a payment Intent was returned, render Stripe/Razorpay UI
if (result.payment) {
if (result.payment.provider === 'STRIPE') {
const clientSecret = result.payment.clientSecret;
// ... pass to Stripe Elements
}
} else {
// Manual payment or 100% discount, order is complete!
}
} catch (error) {
if (isAPIError(error)) {
console.error('Checkout failed:', error.message, error.details);
}
}Using Domain Modules
Every endpoint from the OpenAPI specification is mapped to an easy-to-use module.
Products
// Fetch products with filtering, sorting, and pagination
const response = await sdk.products.getProducts({
categoryId: 'cat_123',
minPrice: 1000, // in paise
maxPrice: 5000,
sort: 'price_asc',
skip: 0,
take: 20
});
console.log(`Found ${response.total} products`);
// Get a single product and its variants
const product = await sdk.products.getProduct('prod_789');
const { variants } = await sdk.products.getVariants('prod_789');Cart & Discounts
// Add an item to the shopping cart
await sdk.cart.addItem({
variantId: 'var_456',
quantity: 2
});
// Apply a discount code
const discountCheck = await sdk.cart.applyDiscount({
code: 'SUMMER25'
});
console.log('Valid:', discountCheck.valid, 'New Total:', discountCheck.total);
// Retrieve full cart state
const cart = await sdk.cart.getCart();Customer & Auth
// Check authentication session
const session = await sdk.auth.getSession();
if (session.authenticated) {
const profile = await sdk.customer.getProfile();
console.log('Logged in as:', profile.name);
} else {
// Get Google OAuth Redirect URL
const { authUrl } = await sdk.auth.getGoogleAuthUrl({
redirectUrl: 'http://localhost:3001/auth/callback'
});
window.location.href = authUrl;
}Advanced: Session Management (Guest Carts)
If you are tracking an unauthenticated user, you can dynamically update the SDK's internal sessionId header so subsequent cart calls correctly identify the guest cart:
// e.g. after verifying local storage
sdk.setSessionId('sess_guest_98765');
// All subsequent calls automatically attach `x-session-id: sess_guest_98765`
await sdk.cart.getCart();Error Handling
All failed SDK responses throw an APIError:
import { isAPIError } from '@eshop/storefront-sdk';
try {
await sdk.cart.applyDiscount({ code: 'INVALID_CODE' });
} catch (error) {
if (isAPIError(error)) {
console.error(`Status: ${error.statusCode}`); // e.g. 400
console.error(`Message: ${error.message}`); // e.g. "Invalid coupon"
} else {
console.error('Network Error:', error);
}
}Architecture Details
- Tree Shakeable: The package outputs both ESM and CJS bundles (
tsup). Types are included. - Dependency Free: Written using Native
fetchwith 0 heavy external dependencies. - Smart Retries: Network failures or 5xx HTTP errors will automatically trigger exponential backoff retries when
retry: > 0is set in the config.
