@storeos/storefront-client
v0.0.4
Published
TypeScript SDK for the StoreOS Storefront REST API (v1).
Downloads
19
Readme
@storeos/storefront-client
The official TypeScript SDK for StoreOS storefronts. Browse products, manage customer accounts, and run checkout — with full types.
Two surfaces ship from the same package:
| Surface | Import | Transport |
| --------------- | ---------------------------------- | ------------------------------- |
| REST client | @storeos/storefront-client | Storefront REST API (fetch) |
| React SDK | @storeos/storefront-client/react | GraphQL + React providers/hooks |
Works anywhere fetch runs: React, Next.js, Remix, React Native, Cloudflare Workers, Node 18+.
Install
npm install @storeos/storefront-clientyarn add @storeos/storefront-clientpnpm add @storeos/storefront-clientbun add @storeos/storefront-clientFor the React SDK, also install peers:
npm install react react-dom @tanstack/react-query zod immer use-immerStoreos Core SDK
import { StoreFront } from '@storeos/storefront-client';
const store = new StoreFront({
tenant: 'your-store-id',
});
const { nodes: products, meta } = await store.getProducts({
page: 1,
limit: 24,
});
const product = await store.getProduct({ handle: 'blue-widget' });Configuration
const store = new StoreFront({
/** Your StoreOS store identifier */
tenant: 'your-store-id',
/** Optional — restore a session from storage */
accessToken: sessionToken,
/** Optional — custom fetch for tests or edge runtimes */
fetch: customFetch,
});Customer sessions
Sign-in methods automatically keep the session on the client. Persist the token in your app and restore it on load:
await store.login({
user: '[email protected]',
password: '••••••••',
});
// Save store.getAccessToken() to cookies, localStorage, etc.
store.setAccessToken(savedToken);
const me = await store.getMe();Phone OTP is supported too:
await store.sendOtp({ phoneNumber: '+8801…' });
await store.verifyOtp({ phoneNumber: '+8801…', otp: '123456' });What you can build
Catalog
await store.getTenant();
await store.getProducts({ search: 'shirt', collectionIds: ['…'] });
await store.getProduct({ handle: 'linen-shirt' });
await store.getCollections();
await store.getCollection('collection-id');Checkout
const coupon = await store.verifyCoupon({
code: 'SAVE10',
lineItems: [{ productId: '…', quantity: 2 }],
});
const { order } = await store.createOrder({
lineItems: [{ productId: '…', quantity: 2 }],
shippingAddress: {
/* … */
},
paymentMethod: 'COD',
couponCode: coupon.valid ? 'SAVE10' : undefined,
});Guest checkout works out of the box. If the API returns a token, the client picks it up so the customer can track the order immediately.
Order history
const { nodes: orders } = await store.getMyOrders({ page: 1 });
await store.getOrder('order-id');
await store.cancelOrder('order-id', 'Changed my mind');Pagination
List methods return { nodes, meta }:
const { nodes, meta } = await store.getProducts({ page: 2, limit: 12 });
meta.totalCount;
meta.hasNextPage;
meta.totalPages;Supported query params: page, limit, sort, sortBy, search, and collectionIds (products).
Errors
Non-2xx responses throw StoreFrontApiError with status, message, and body:
import { StoreFront, StoreFrontApiError } from '@storeos/storefront-client';
try {
await store.getProduct({ handle: 'sold-out' });
} catch (error) {
if (error instanceof StoreFrontApiError) {
console.error(error.status, error.body);
}
}Types
Every method is fully typed. Import request and response shapes directly:
import type {
Product,
Collection,
Order,
StorefrontUser,
CreateOrderInput,
PaginatedResponse,
} from '@storeos/storefront-client';API surface
| Area | Methods |
| --------------- | ------------------------------------------------------------------------------------------------- |
| Store | getTenant |
| Products | getProducts, getProduct, getProductById, getProductByHandle |
| Collections | getCollections, getCollection |
| Auth | getMe, register, login, logout, updateProfile, changePassword, sendOtp, verifyOtp |
| Orders | getMyOrders, getOrder, createOrder, verifyCoupon, cancelOrder |
| Session | getAccessToken, setAccessToken |
React SDK
GraphQL-based providers, hooks, queries, validation, and Next.js server helpers for storefront UIs.
Entry points
| Import | Use for |
| ------------------------------------------ | ---------------------------------------------------------------- |
| @storeos/storefront-client/react | Client providers, hooks, GraphQL client, utils, checkout schemas |
| @storeos/storefront-client/react/server | Next.js server GraphQL client + getServerSession |
| @storeos/storefront-client/react/queries | Shared GraphQL query/mutation strings (RSC-safe) |
| @storeos/storefront-client/react/types | Enums and GraphQL-aligned types (RSC-safe) |
Setup
Wrap your app with React Query and StoreOSProvider (auth uses @tanstack/react-query):
'use client';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { StoreOSProvider } from '@storeos/storefront-client/react';
const queryClient = new QueryClient();
export function Providers({ children }: { children: React.ReactNode }) {
return (
<QueryClientProvider client={queryClient}>
<StoreOSProvider
config={{
apiUrl: 'https://storefront-api.storeos.dev',
tenant: 'your-store-id',
siteUrl: 'https://your-store.com',
// optional:
// auth: { cookieName: 'auth_token', cookieMaxAge: 60 * 60 * 24 * 30 },
// cart: { storageKey: 'cart' },
// currency: { code: 'BDT', locale: 'en-BD' },
}}
>
{children}
</StoreOSProvider>
</QueryClientProvider>
);
}StoreOSProvider initializes config and mounts auth + cart context.
Config options
| Field | Default | Description |
| --------------------------- | ------------------------------------ | ------------------------------- |
| apiUrl | https://storefront-api.storeos.dev | Storefront GraphQL base |
| tenant | — (required) | Store identifier (x-tenant) |
| siteUrl | "" | Public site URL helpers |
| staticFileBaseUrl | https://cdn.storeos.dev | CDN base for media |
| auth.cookieName | auth_token | Session cookie name |
| auth.cookieMaxAge | 30 days | Cookie max-age (seconds) |
| auth.tokenPollingInterval | 2000 | Client token poll interval (ms) |
| cart.storageKey | cart | localStorage key for cart |
| currency.code / locale | BDT / en-BD | Money formatting defaults |
Auth
import { useAuth, useSession } from '@storeos/storefront-client/react';
function AccountMenu() {
const { session, login, logout, loading } = useAuth();
// or: const session = useSession();
if (loading) return null;
if (!session.user) {
return (
<button
onClick={() =>
login({ user: '[email protected]', password: '••••••••' })
}
>
Sign in
</button>
);
}
return (
<div>
<span>{session.user.name ?? session.user.email}</span>
<button onClick={() => logout()}>Sign out</button>
</div>
);
}Token helpers (cookie-backed):
import {
getAuthToken,
setCookieAuthToken,
removeCookieAuthToken,
} from '@storeos/storefront-client/react';Cart
Persists to localStorage and exposes drawer state + totals:
import { useCart } from '@storeos/storefront-client/react';
import type { CartLineItem } from '@storeos/storefront-client/react';
function AddToCartButton({ item }: { item: CartLineItem }) {
const { addItem, totalItems } = useCart();
return (
<button onClick={() => addItem(item)}>Add to cart ({totalItems})</button>
);
}| API | Description |
| --------------------------------------------------------- | ------------------ |
| lineItems | Current cart lines |
| addItem / removeItem / adjustQuantity / clearCart | Mutate cart |
| subTotalAmount / totalItems | Derived totals |
| cartDrawerOpen / setCartDrawerOpen | Drawer UI state |
GraphQL (client)
import { useQuery } from '@tanstack/react-query';
import { gqlClient } from '@storeos/storefront-client/react';
import { PRODUCTS_QUERY } from '@storeos/storefront-client/react/queries';
function ProductGrid() {
const { data } = useQuery({
queryKey: ['products'],
queryFn: () =>
gqlClient<{ products: { nodes: unknown[] } }>({
query: PRODUCTS_QUERY,
variables: { page: 1, limit: 24 },
}),
});
return /* render data.products.nodes */;
}Auth token and x-tenant are attached automatically from config / cookies.
Next.js server
import {
getServerSession,
gqlServerClient,
} from '@storeos/storefront-client/react/server';
import { PRODUCTS_QUERY } from '@storeos/storefront-client/react/queries';
import { initStoreOS } from '@storeos/storefront-client/react';
// Call once in a server entry (layout/provider) before using server helpers
initStoreOS({
apiUrl: process.env.STOREOS_API_URL!,
tenant: process.env.STOREOS_TENANT!,
});
export default async function Page() {
const session = await getServerSession();
const data = await gqlServerClient({
query: PRODUCTS_QUERY,
variables: { page: 1, limit: 12 },
});
return /* … */;
}getServerSession reads the auth cookie and resolves me via GraphQL.
Variant selection
import { useVariantSelection } from '@storeos/storefront-client/react';
function VariantPicker({ product }) {
const {
selectedAttributes,
setSelectedAttributes,
selectedVariant,
isOptionAvailable,
} = useVariantSelection({
variants: product.variants,
variantConfigs: product.variantConfigs,
productId: product._id,
});
// Only valid combinations are stored; impossible option combos are normalized away.
}Checkout validation
Zod schemas for guest vs logged-in checkout:
import {
checkoutFormSchema,
loggedInCheckoutFormSchema,
getCheckoutFormSchema,
} from '@storeos/storefront-client/react';
import type { CheckoutFormData } from '@storeos/storefront-client/react';
const schema = getCheckoutFormSchema(isLoggedIn);
const parsed = schema.parse(formValues);Utilities
import {
formatCurrency,
formatAmount,
getFileUrl,
createUrl,
getSiteUrl,
getDeliveryCharge,
calculateOrderTotal,
getDeliveryAreaDisplayName,
getVariantFromSelection,
isVariantOptionAvailable,
} from '@storeos/storefront-client/react';Queries & types
Import GraphQL documents and shared enums/types without pulling in client-only code:
import {
ME_QUERY,
LOGIN_MUTATION,
PRODUCTS_QUERY,
PRODUCT_BY_ID_QUERY,
SEARCH_PRODUCTS_QUERY,
COLLECTIONS_QUERY,
CREATE_ORDER_MUTATION,
MY_ORDERS_QUERY,
ORDER_DETAILS_QUERY,
CANCEL_ORDER_MUTATION,
VERIFY_COUPON_MUTATION,
STOREFRONT_QUERY,
} from '@storeos/storefront-client/react/queries';
import {
DeliveryArea,
Invoice_Payment_Method,
Invoice_Status,
ProductStatus,
} from '@storeos/storefront-client/react/types';React surface
| Area | Exports |
| ------------------- | ------------------------------------------------------------------------------ |
| Provider | StoreOSProvider, initStoreOS, getConfig |
| Auth | useAuth, useSession, StoreOSAuthProvider, cookie token helpers |
| Cart | useCart, StoreOSCartProvider |
| GraphQL | gqlClient, gql (client); gqlServerClient, getServerSession (server) |
| Variants | useVariantSelection |
| Validation | checkoutFormSchema, loggedInCheckoutFormSchema, getCheckoutFormSchema, … |
| Utils | currency, URLs, delivery, variant helpers |
| Queries / types | @storeos/storefront-client/react/queries, …/react/types |
License
Private / see storeos.dev for terms.
