npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@commercengine/storefront-sdk

v0.14.2

Published

TypeScript SDK for the Storefront API

Downloads

1,108

Readme

Storefront SDK

A powerful, type-safe TypeScript SDK for the CommerceEngine Storefront API. Built with modern JavaScript patterns, automatic token management, and comprehensive error handling.

Breaking changes from the previous SDK surface are documented in MIGRATION.md.

If you are building an application on an official framework wrapper such as Next.js, prefer @commercengine/storefront. This package is the standalone isomorphic core SDK for SPA usage, advanced custom integrations, and framework bindings.

✨ Key Features:

  • 100% Type Safe: Every API endpoint is fully typed with TypeScript
  • Automatic Token Management: Built-in refresh token logic for seamless authentication
  • Universal Compatibility: Works in browser, Node.js, and hybrid rendering environments
  • Production Ready: Implements all API best practices out of the box
  • Zero Configuration: Works with sensible defaults, extensive customization available

Installation

npm install @commercengine/storefront-sdk
yarn add @commercengine/storefront-sdk
pnpm add @commercengine/storefront-sdk

Quick Start

import {
  BrowserTokenStorage,
  Environment,
  createStorefront,
} from "@commercengine/storefront-sdk";

const storefront = createStorefront({
  storeId: "your-store-id",
  environment: Environment.Staging,
  apiKey: "your-api-key",
  session: {
    tokenStorage: new BrowserTokenStorage("myapp_"),
  },
});

// Public reads never touch session lifecycle
const { data: products } = await storefront.public().catalog.listProducts();

// User-scoped APIs can resolve user_id from the active session automatically
const { data: wishlist } = await storefront.session().cart.getWishlist();

createStorefront() returns one cached public SDK and one cached default session SDK for that factory instance. Use storefront.session(overrides) only for one-off, token-seeded/stateless cases that should not reuse the default session client.

Configuration Options

The SDK supports extensive configuration to fit your needs:

Recommended Factory Pattern

const storefront = createStorefront({
  // Required
  storeId: "your-store-id",
  
  // Environment (optional, defaults to Production)
  environment: Environment.Staging, // or Environment.Production
  
  // API key for public and session-backed requests
  apiKey: "your-api-key",
});

Session Defaults

const storefront = createStorefront({
  storeId: "your-store-id",
  environment: Environment.Production,
  apiKey: "your-api-key",
  
  // Custom base URL (optional, overrides environment) - Not needed for most implementations
  baseUrl: "https://your-custom-api.example.com",
  
  // Request Configuration
  timeout: 10000,                          // Request timeout in milliseconds
  
  // Default Headers (auto applied to all applicable requests)
  defaultHeaders: {
    customer_group_id: "01JHS28V83KDWTRBXXJQRTEKA0", // For pricing and promotions
  },
  
  // Debug and Logging
  debug: true,                             // Enable detailed request/response logging - Uses console.log by default
  logger: console.log,                     // Custom logger function - structure your logs any way you want. Also helpful to pipe logs into external services

  session: {
    // Token Management
    accessToken: "initial-access-token",   // Initial access token
    refreshToken: "initial-refresh-token", // Initial refresh token (for automatic mode)
    tokenStorage: new BrowserTokenStorage("myapp_"),
  },
});

Direct Session SDK (Advanced)

If you only need the session-aware client directly, you can still instantiate it yourself:

import {
  BrowserTokenStorage,
  Environment,
  SessionStorefrontSDK,
} from "@commercengine/storefront-sdk";

const sdk = new SessionStorefrontSDK({
  storeId: "your-store-id",
  environment: Environment.Staging,
  apiKey: "your-api-key",
  tokenStorage: new BrowserTokenStorage("myapp_"),
});

If you need the raw public transport classes directly, the advanced exports are also available:

import {
  PublicStorefrontAPIClient,
  PublicStorefrontSDK,
  SessionStorefrontAPIClient,
  SessionStorefrontSDK,
} from "@commercengine/storefront-sdk";

Token Management

The SDK supports three primary access patterns:

1. Managed Sessions (Recommended)

Managed mode is enabled when you provide tokenStorage. The SDK can then:

  • Persist tokens
  • Refresh expired tokens
  • Bootstrap an anonymous session on the first token-required request
  • Resolve user_id automatically for user-scoped methods
import {
  BrowserTokenStorage,
  SessionStorefrontSDK,
} from "@commercengine/storefront-sdk";

const sdk = new SessionStorefrontSDK({
  storeId: "your-store-id",
  apiKey: "your-api-key",
  tokenStorage: new BrowserTokenStorage("myapp_"),
});

2. Manual Sessions

Manual mode is enabled when you set tokens directly (accessToken or sdk.setTokens) without tokenStorage. The SDK uses the token you provide but does not auto-refresh or auto-persist sessions.

const storefront = createStorefront({
  storeId: "your-store-id",
  apiKey: "your-api-key",
});

const sdk = storefront.session();

const { data } = await sdk.auth.loginWithPassword({
  email: "[email protected]",
  password: "password",
});

if (data) {
  await sdk.setTokens(data.access_token, data.refresh_token);
}

For stateless/token-seeded requests, create a one-off session client:

const sdk = storefront.session({
  accessToken: "existing-access-token",
  refreshToken: "existing-refresh-token",
});

3. Public Client

Use storefront.public() when a flow should stay API-key-backed and never participate in session bootstrap, refresh, or token persistence.

Session Helpers (sdk.session)

Use sdk.session when you need explicit control over passive vs active session reads.

  • peek* methods are passive reads and never mint/refresh.
  • ensure* methods can mint/refresh in managed mode.
// Passive read (no side effects)
const userId = await sdk.session.peekUserId();

// Active resolution (may mint or refresh in managed mode)
const resolvedUserId = await sdk.session.ensureUserId();

Token Storage Options

Choose the storage method that fits your environment:

Browser localStorage

import { BrowserTokenStorage } from "@commercengine/storefront-sdk";

const tokenStorage = new BrowserTokenStorage("myapp_"); // Optional prefix

Browser cookies (for browser persistence or cross-tab sync)

import { CookieTokenStorage } from "@commercengine/storefront-sdk";

const tokenStorage = new CookieTokenStorage({
  prefix: "myapp_",
  maxAge: 7 * 24 * 60 * 60, // 7 days
  secure: true,
  sameSite: "Lax",
});

CookieTokenStorage uses document.cookie and is browser-only. It is useful for browser cookie persistence and cross-tab visibility, but it is not request-aware SSR storage. For framework server/client continuity, use an official wrapper from @commercengine/storefront or a request-aware storage adapter from @commercengine/ssr-utils.

Memory (for server-side or temporary storage)

import { MemoryTokenStorage } from "@commercengine/storefront-sdk";

const tokenStorage = new MemoryTokenStorage();

Custom Storage

class CustomTokenStorage implements TokenStorage {
  async getAccessToken(): Promise<string | null> {
    // Your implementation
  }
  
  async setAccessToken(token: string): Promise<void> {
    // Your implementation
  }
  
  // ... implement other required methods
}

Authentication

If you use managed sessions (tokenStorage), you usually do not need to call anonymous auth manually. The SDK can bootstrap anonymous sessions automatically on token-required requests.

That lazy bootstrap is a core SDK capability, not necessarily the primary app pattern for every framework. For official framework wrappers, the recommended pattern is still to bootstrap explicitly in app code when later server-side session reads depend on established cookie continuity.

Anonymous Authentication

// Optional: manually create an anonymous session
const { data } = await sdk.auth.getAnonymousToken();
if (data) {
  await sdk.setTokens(data.access_token, data.refresh_token);
}

Phone/Email Authentication

// Step 1: Initiate login
const { data: otpData } = await sdk.auth.loginWithPhone({
  phone: "9876543210",
  country_code: "+91",
  register_if_not_exists: true,
});

// Step 2: Verify OTP
if (otpData) {
  const { data: authData } = await sdk.auth.verifyOtp({
    otp: "123456",
    otp_token: otpData.otp_token,
    otp_action: otpData.otp_action,
  });
  
  if (authData) {
    await sdk.setTokens(authData.access_token, authData.refresh_token);
  }
}

Password Authentication

const { data } = await sdk.auth.loginWithPassword({
  email: "[email protected]",
  password: "your-password",
});

if (data) {
  await sdk.setTokens(data.access_token, data.refresh_token);
}

API Clients & Complete Type Safety

The SDK provides complete access to every CommerceEngine API endpoint with full TypeScript support. All clients are automatically generated from the OpenAPI specification, ensuring 100% accuracy and type safety.

Available Clients

// Authentication & User Management
sdk.auth.*     // Login, registration, OTP, password management
sdk.customer.* // Customer profiles, addresses, preferences

// E-commerce Core
sdk.catalog.*  // Products, categories, search, variants
sdk.cart.*     // Cart management, coupons, promotions
sdk.order.*    // Order creation, tracking, history

// Supporting Services  
sdk.helpers.*  // Countries, currencies, utilities
sdk.store.*    // Store config and health endpoints

Example Usage

// Every method is fully typed - IntelliSense shows all available parameters
const { data: products } = await sdk.catalog.listProducts({
  query: {
    page: 1,
    limit: 20,
    category_id: "electronics",
    sort: "price_asc",
  }
});

// Get product details
const { data: product } = await sdk.catalog.getProduct({
  product_id_or_slug: "product-id"
});

// Create a cart with full type checking
const { data: cart } = await sdk.cart.createCart({
  items: [
    {
      product_id: "product-id",
      quantity: 2,
      variant_id: "variant-id",
    }
  ]
});

📚 API Reference: For complete endpoint documentation, parameters, and response schemas, visit docs.commercengine.io/api-reference

User Information & JWT Utilities

The top-level getters are passive lookups. They never mint or refresh a session:

// Passive reads from the current token
const userInfo = await sdk.getUserInfo();
console.log(userInfo?.userId, userInfo?.email, userInfo?.customerId);

// Check authentication status
const isLoggedIn = await sdk.isLoggedIn();
const isAnonymous = await sdk.isAnonymous();

// Get specific user data
const userId = await sdk.getUserId();
const customerId = await sdk.getCustomerId();
const customerGroupId = await sdk.getCustomerGroupId();

Use sdk.session.ensure* for active resolution:

const userId = await sdk.session.ensureUserId();
const accessToken = await sdk.session.ensureAccessToken();

For user-scoped APIs, user_id can be omitted and resolved automatically in managed mode:

await sdk.cart.getWishlist();
await sdk.customer.listAddresses();
await sdk.order.listOrders({ page: 1, limit: 20 });

Error Handling

All API calls return a consistent ApiResult<T> structure with full error information:

const { data, error, response } = await sdk.catalog.listProducts();

if (error) {
  console.error("API Error:", error.message, error.code);
  console.log("Status:", response.status);
} else {
  console.log("Success:", data);
}

Network Error Handling

const result = await sdk.catalog.getProduct({ product_id_or_slug: "invalid-id" });

if (result.error) {
  switch (result.error.code) {
    case "NETWORK_ERROR":
      console.log("Network connection failed");
      break;
    case "UNAUTHORIZED":
      console.log("Authentication required");
      break;
    default:
      console.log("API Error:", result.error.message);
  }
}

Debug Mode

Enable detailed logging for development:

const sdk = new SessionStorefrontSDK({
  storeId: "your-store-id",
  debug: true,
  // Optional: Pass a custom logger 
  logger: (message, data) => {
    console.log(`[SDK Debug] ${message}`, data);
  },
});

Debug mode logs:

  • Request URLs, methods, headers, and bodies
  • Response status, headers, and bodies
  • Token refresh attempts and results
  • Network errors and retry attempts

TypeScript Support

The SDK is built with TypeScript-first design:

import type { 
  ApiResult, 
  UserInfo, 
  DebugLoggerFn,
  SupportedDefaultHeaders 
} from "@commercengine/storefront-sdk";

// All API responses are properly typed
const { data }: ApiResult<ProductListResponse> = await sdk.catalog.listProducts();

// IntelliSense works for all nested properties
console.log(data?.products[0].name);

Universal Compatibility

The SDK works seamlessly across all JavaScript environments:

Client-Side Applications

  • React, Vue, Angular: Use BrowserTokenStorage for persistent sessions
  • Automatic token refresh: Handles token expiry transparently
  • Cross-tab synchronization: With CookieTokenStorage

Server-Side Applications

  • Node.js, Bun, Deno: Use MemoryTokenStorage or custom storage
  • API routes: Perfect for Next.js API routes, Express middleware
  • Background jobs: Reliable token management for long-running processes

Hybrid Rendering (SSR/SSG)

  • Official framework wrappers: Prefer @commercengine/storefront
  • Custom SSR integrations: Use request-aware storage from @commercengine/ssr-utils
  • CookieTokenStorage: Browser-only cookie persistence, not server request storage
  • Hydration-safe setups: depend on framework-aware request storage, not document.cookie

Best Practices Built-In

The SDK implements CommerceEngine API best practices automatically:

  • Automatic token refresh before expiry
  • Proper error handling for all edge cases
  • Request retries for transient failures
  • Rate limiting compliance with proper backoff
  • Security headers and CSRF protection
  • Timeout handling with configurable limits
  • Memory leak prevention with proper cleanup

Contributing

Version Management with Changeset

This project uses Changeset for version management and publishing. Here's how to contribute:

Creating Changes

When you make changes to the SDK, create a changeset to document them:

pnpm changeset

This will prompt you to:

  • Select the type of change (patch/minor/major)
  • Write a summary of what changed
  • Create a markdown file in the .changeset/ folder

Version Types

  • Patch (0.0.x): Bug fixes, documentation updates, internal refactoring
  • Minor (0.x.0): New features, new API endpoints, backwards-compatible changes
  • Major (x.0.0): Breaking changes, API modifications that affect existing code

Release Process

  1. During Development: Create changesets for your changes

    pnpm changeset
  2. Before Release: Consume changesets and update versions

    pnpm version

    This updates package.json, generates/updates CHANGELOG.md, and removes consumed changesets.

  3. Publishing: Build and publish to npm

    pnpm release

Available Scripts

  • pnpm changeset - Create a new changeset
  • pnpm run version - Consume changesets and bump version
  • pnpm run release - Build and publish to npm

The changeset workflow ensures proper semantic versioning, comprehensive changelogs, and coordinated releases.

License

All Rights Reserved