@commercengine/ssr-utils
v0.1.0
Published
Framework-agnostic SSR utilities for Commerce Engine SDKs
Maintainers
Readme
@commercengine/ssr-utils
Framework-agnostic SSR utilities for Commerce Engine SDKs. Provides shared token storage and cookie handling that works across all major meta-frameworks.
Note: This is a low-level utility package. For Next.js projects, use
@commercengine/storefront-sdk-nextjswhich builds on this package and provides a complete solution with request isolation, universal API, automatic context detection, and React integration.
Features
- Universal Cookie Adapter - Abstract interface that works with any framework's cookie API
- Server Token Storage - Request-scoped token storage for SSR contexts
- Build-Time Caching - Intelligent token caching for SSG/ISR builds
- Environment Detection - Utilities to detect server, client, and build contexts
- Zero Dependencies - Lightweight, no framework-specific dependencies
Installation
npm install @commercengine/ssr-utils
# or
pnpm add @commercengine/ssr-utilsQuick Start
For Next.js users: Skip this section and use
@commercengine/storefront-sdk-nextjsinstead. It handles request isolation, client/server detection, build optimization, and provides a much simpler API.
The examples below show how to use ssr-utils directly for building framework-specific integrations (like we did for Next.js) or for frameworks without an official SDK wrapper.
Basic Usage (Any Framework)
import { ServerTokenStorage } from '@commercengine/ssr-utils';
import { StorefrontSDK } from '@commercengine/storefront-sdk';
// Create adapter for your framework's cookie API
const tokenStorage = new ServerTokenStorage({
get: (name) => /* get cookie by name */,
set: (name, value, opts) => /* set cookie */,
delete: (name) => /* delete cookie */,
});
const sdk = new StorefrontSDK({
storeId: 'your-store-id',
apiKey: 'your-api-key',
tokenStorage,
});SvelteKit
// src/routes/+page.server.ts
import { ServerTokenStorage } from '@commercengine/ssr-utils';
import { StorefrontSDK } from '@commercengine/storefront-sdk';
import { env } from '$env/dynamic/private';
export async function load({ cookies }) {
const tokenStorage = new ServerTokenStorage({
get: (name) => cookies.get(name) ?? null,
set: (name, value, opts) => cookies.set(name, value, opts),
delete: (name) => cookies.delete(name),
});
const sdk = new StorefrontSDK({
storeId: env.STORE_ID,
apiKey: env.API_KEY,
tokenStorage,
});
const { data } = await sdk.catalog.listProducts();
return { products: data?.products ?? [] };
}Nuxt (h3)
// server/api/products.ts
import { getCookie, setCookie, deleteCookie, defineEventHandler } from 'h3';
import { ServerTokenStorage } from '@commercengine/ssr-utils';
import { StorefrontSDK } from '@commercengine/storefront-sdk';
export default defineEventHandler(async (event) => {
const tokenStorage = new ServerTokenStorage({
get: (name) => getCookie(event, name) ?? null,
set: (name, value, opts) => setCookie(event, name, value, opts),
delete: (name) => deleteCookie(event, name),
});
const sdk = new StorefrontSDK({
storeId: process.env.STORE_ID!,
apiKey: process.env.API_KEY!,
tokenStorage,
});
const { data } = await sdk.catalog.listProducts();
return { products: data?.products ?? [] };
});Astro
// src/pages/products.astro
---
import { ServerTokenStorage } from '@commercengine/ssr-utils';
import { StorefrontSDK } from '@commercengine/storefront-sdk';
const tokenStorage = new ServerTokenStorage({
get: (name) => Astro.cookies.get(name)?.value ?? null,
set: (name, value, opts) => Astro.cookies.set(name, value, opts),
delete: (name) => Astro.cookies.delete(name),
});
const sdk = new StorefrontSDK({
storeId: import.meta.env.STORE_ID,
apiKey: import.meta.env.API_KEY,
tokenStorage,
});
const { data } = await sdk.catalog.listProducts();
const products = data?.products ?? [];
---
<ul>
{products.map(product => <li>{product.name}</li>)}
</ul>API Reference
ServerTokenStorage
Cookie-based token storage for server-side rendering contexts.
import { ServerTokenStorage, type CookieAdapter } from '@commercengine/ssr-utils';
const adapter: CookieAdapter = {
get: (name) => /* get cookie value */,
set: (name, value, options) => /* set cookie */,
delete: (name) => /* delete cookie */,
};
const storage = new ServerTokenStorage(adapter, {
prefix: 'ce_', // Cookie name prefix (default: 'ce_')
maxAge: 2592000, // Cookie max age in seconds (default: 30 days)
path: '/', // Cookie path (default: '/')
domain: undefined, // Cookie domain (default: current domain)
secure: true, // HTTPS only (default: auto-detect)
sameSite: 'lax', // SameSite attribute (default: 'lax')
});BuildCachingTokenStorage
In-memory token storage with caching for SSG/ISR build contexts. Tokens are cached and reused across pages during static generation.
import { BuildCachingTokenStorage } from '@commercengine/ssr-utils';
const storage = new BuildCachingTokenStorage({
cacheKey: 'my-store:production', // Unique key for caching
ttlSeconds: 300, // Cache TTL (default: 5 minutes)
});Environment Detection
Utilities to detect the current execution context.
import { isServer, isClient, isBuildContext } from '@commercengine/ssr-utils';
// Check if running on server
if (isServer()) {
// Server-side code
}
// Check if running in browser
if (isClient()) {
// Client-side code
}
// Check if running during static build
if (isBuildContext()) {
// Build-time code (SSG/ISR)
}
// Custom build detection
if (isBuildContext({
envVars: ['NEXT_IS_BUILD', 'NUXT_BUILD', 'CI']
})) {
// Custom environment variable detection
}createTokenStorage
Factory function to create the appropriate token storage based on context.
import { createTokenStorage } from '@commercengine/ssr-utils';
const tokenStorage = createTokenStorage({
cookieAdapter: adapter, // Optional: cookie adapter for server contexts
buildCacheKey: 'my-store', // Optional: enables build-time caching
options: { // Optional: storage options
prefix: 'ce_',
maxAge: 2592000,
},
});Types
CookieAdapter
Framework-agnostic interface for cookie operations.
interface CookieAdapter {
get(name: string): string | null;
set(name: string, value: string, options?: CookieOptions): void;
delete(name: string): void;
}CookieOptions
Standard cookie options that work across frameworks.
interface CookieOptions {
maxAge?: number; // Seconds until expiry
path?: string; // Cookie path
domain?: string; // Cookie domain
secure?: boolean; // HTTPS only
sameSite?: 'strict' | 'lax' | 'none'; // SameSite attribute
httpOnly?: boolean; // HTTP only (no JS access)
}SSRTokenStorageOptions
Configuration for token storage instances.
interface SSRTokenStorageOptions {
prefix?: string; // Cookie name prefix
maxAge?: number; // Cookie max age
path?: string; // Cookie path
domain?: string; // Cookie domain
secure?: boolean; // HTTPS only
sameSite?: 'strict' | 'lax' | 'none'; // SameSite attribute
}TokenStorage
Interface that all token storage implementations follow.
interface TokenStorage {
getAccessToken(): Promise<string | null>;
setAccessToken(token: string): Promise<void>;
getRefreshToken(): Promise<string | null>;
setRefreshToken(token: string): Promise<void>;
clearTokens(): Promise<void>;
}Build Cache API
Low-level API for direct cache manipulation (advanced use cases).
import {
getCachedToken,
setCachedToken,
clearCachedToken,
clearAllCachedTokens,
getCacheStats,
} from '@commercengine/ssr-utils';
// Get cached token
const token = getCachedToken('my-store', 'access');
// Set cached token with TTL
setCachedToken('my-store', 'access', 'token-value', 300);
// Clear specific token
clearCachedToken('my-store', 'access');
// Clear all cached tokens
clearAllCachedTokens();
// Get cache statistics
const stats = getCacheStats();
// { size: 2, keys: ['my-store:access', 'my-store:refresh'] }Why ssr-utils?
The Problem
Every SSR framework has its own cookie API:
- Next.js:
cookies()fromnext/headers - SvelteKit:
cookiesparameter in load functions - Nuxt/h3:
getCookie(),setCookie()from h3 - Astro:
Astro.cookies
Building a production-ready SDK integration for each framework requires solving:
- Cookie-based token storage
- Build-time token caching for SSG/ISR
- Environment detection (server/client/build)
The Solution
ssr-utils extracts the common building blocks so framework-specific SDKs can focus on framework-specific concerns:
| Layer | Responsibility | |-------|----------------| | ssr-utils | Cookie abstraction, token storage, build caching | | Framework SDK (e.g., nextjs) | Request isolation, context detection, DX patterns, React integration |
This package is for:
- Building new framework-specific SDK wrappers (SvelteKit, Nuxt, Astro, etc.)
- Advanced users who need low-level control
- Frameworks without an official SDK wrapper
Use the framework SDK instead if available:
- Next.js →
@commercengine/storefront-sdk-nextjs
Related Packages
@commercengine/storefront-sdk- Core Storefront SDK@commercengine/storefront-sdk-nextjs- Next.js integration (uses this package)@commercengine/pos- Point of Sale SDK
License
All Rights Reserved
