@sixtyninecommerce/client
v0.3.0
Published
JavaScript/TypeScript client for sixtynine-commerce storefronts
Readme
@sixtyninecommerce/client
JavaScript/TypeScript client for sixtynine-commerce storefronts.
Install
npm install @sixtyninecommerce/clientQuick Start
import { createStorefrontClient } from '@sixtyninecommerce/client';
const client = await createStorefrontClient({
storeCode: 'my-store',
cdnUrl: 'https://cdn.my-store.com',
// Optional: retry transient GETs (default { attempts: 2, baseDelayMs: 200 })
retry: { attempts: 3, baseDelayMs: 200 },
// Optional: notified when the customer's auth token is rejected
onAuthExpired: () => router.push('/sign-in'),
});
// Products
const product = await client.commerce.getProduct('blue-shirt');
const results = await client.commerce.searchProducts({ term: 'shirt' });
// Cart
await client.commerce.addToCart(product.variants[0].id, 1);
const order = await client.commerce.getActiveOrder();
// Customer subscriptions, VAT validation, MyParcel shipping
const subs = await client.commerce.getMySubscriptions();
const vat = await client.commerce.getMyVatValidationStatus();
const dropOffs = await client.commerce.getDropOffPoints({ postalCode: '1011AB' });
const tracking = await client.commerce.trackShipment('3SXXXXXX', '1011AB');
// CMS content
const page = await client.content.resolvePath('/about-us');
const menu = await client.content.getMenu('main-menu');
const sitemap = await client.content.getSitemap('en');
// Resolve CMS reference fields (image[], content_item[], etc.)
const images = await client.content.lookupAssets(item.values.gallery);
const linked = await client.content.lookupContentItems(item.values.related_posts);
// Routes
const routes = await client.navigation.getRoutes();
// Cancel a slow read (typeahead, page navigation, SSR)
const controller = new AbortController();
const results = await client.commerce.searchProducts(
{ term: 'shoes' },
{ signal: controller.signal }
);
// AbortSignal is supported on read methods (catalog, content, navigation, sitemap)
// Mutations (cart, checkout, customer auth) intentionally don't accept signal.
// Pricing helpers
client.pricing.formatPrice(2999, 'EUR'); // "€29.99"
client.pricing.getTierForQuantity(variant.priceTiers, 10);
client.pricing.validateOrderMinimums(order, { minOrderAmount: 5000 });
// Media helpers
client.media.assetUrl('shop/source/photo.jpg');
client.media.getPresetUrl(asset, 'm', 'webp');
client.media.getResponsiveImageData(asset); // { src, srcSet, sizes, alt }
// Language & auth
client.setLanguage('nl');
client.setAuthToken(token);
// Escape hatch for custom queries
const data = await client.graphql(`query { activeChannel { id } }`);Modules
| Module | Description |
|--------|-------------|
| commerce | Products, collections, search, cart, checkout, customer auth |
| content | CMS resolve, content items, assets, forms, content strings, menus |
| navigation | Unified route manifest, route lookup |
| pricing | Price formatting, tier lookup, order validation (pure functions) |
| media | CDN URLs, preset URLs, responsive image data (pure functions) |
| currency | Exchange rates, currency conversion |
Tree-Shakeable Imports
// Import only pricing (no network code)
import { formatPrice, getTierForQuantity } from '@sixtyninecommerce/client/pricing';
// Import only media helpers
import { PRESETS, getResponsiveImageData } from '@sixtyninecommerce/client/media';Error Handling
Cart and checkout mutations throw MutationError with the Vendure error code:
import { MutationError } from '@sixtyninecommerce/client';
try {
await client.commerce.addToCart(variantId, 100);
} catch (error) {
if (error instanceof MutationError) {
// error.errorCode — "INSUFFICIENT_STOCK_ERROR"
// error.message — "Only 3 items available"
// error.fields — { quantityAvailable: 3 }
}
}Requirements
- Node.js 20+ / modern browser / edge runtime
- Standard
fetchAPI (inject custom fetch via config for SSR)
