@commercengine/ssr-utils
v0.3.1
Published
Framework-agnostic cookie-backed SSR session utilities for Commerce Engine SDKs
Downloads
220
Maintainers
Readme
@commercengine/ssr-utils
Framework-agnostic cookie-backed SSR session utilities for Commerce Engine SDK integrations.
This package provides two levels of API:
createSSRFactory(recommended) — a generic factory that handles singleton scoping, isomorphic token storage, and deduped client bootstrap. Framework bindings provide only the SDK construction callbacks and a server cookie adapter.Low-level primitives —
ServerTokenStorage,ClientTokenStorage, andCookieAdapterfor manual wiring when full control is needed.
For Next.js and TanStack Start projects, prefer
@commercengine/storefront— it ships ready-made wrappers at/nextjsand/tanstack-startthat build oncreateSSRFactory.
Installation
npm install @commercengine/ssr-utils
# or
pnpm add @commercengine/ssr-utilsQuick Start — createSSRFactory
The factory centralizes the orchestration every SSR framework binding needs: isomorphic token storage selection, client/public singleton caching, and deduped client-side session bootstrap.
The framework author provides:
| Callback | Purpose |
| ------------------------- | ---------------------------------------------------- |
| createPublicSDK | Build the public (API-key-only) SDK — cached once |
| createClientSessionSDK | Build a client session SDK with document.cookie storage |
| createServerSessionSDK | Build a server session SDK with request-scoped cookie storage |
| createServerCookieAdapter | Convert a framework request context into a CookieAdapter |
| bootstrapSession | (optional) Client-side bootstrap callback |
SvelteKit
import { createSSRFactory } from "@commercengine/ssr-utils";
import {
PublicStorefrontSDK,
SessionStorefrontSDK,
Environment,
} from "@commercengine/storefront-sdk";
import type { Cookies } from "@sveltejs/kit";
const config = {
storeId: env.PUBLIC_STORE_ID,
apiKey: env.PUBLIC_API_KEY,
environment: Environment.Staging,
};
export const storefront = createSSRFactory<
PublicStorefrontSDK,
SessionStorefrontSDK,
Cookies
>({
createPublicSDK: () => new PublicStorefrontSDK(config),
createClientSessionSDK: (tokenStorage) =>
new SessionStorefrontSDK({ ...config, tokenStorage }),
createServerSessionSDK: (_cookies, tokenStorage) =>
new SessionStorefrontSDK({ ...config, tokenStorage }),
createServerCookieAdapter: (cookies) => ({
get: (name) => cookies.get(name) ?? null,
set: (name, value, opts) => cookies.set(name, value, opts),
delete: (name) => cookies.delete(name),
}),
bootstrapSession: (sdk) => sdk.ensureAccessToken().then(() => {}),
});
// +page.server.ts
export async function load({ cookies }) {
const sdk = storefront.session(cookies);
const { data } = await sdk.cart.getCart();
return { cart: data };
}Nuxt / h3
import { createSSRFactory } from "@commercengine/ssr-utils";
import {
PublicStorefrontSDK,
SessionStorefrontSDK,
Environment,
} from "@commercengine/storefront-sdk";
import { getCookie, setCookie, deleteCookie, type H3Event } from "h3";
const config = {
storeId: process.env.STORE_ID!,
apiKey: process.env.API_KEY!,
environment: Environment.Production,
};
export const storefront = createSSRFactory<
PublicStorefrontSDK,
SessionStorefrontSDK,
H3Event
>({
createPublicSDK: () => new PublicStorefrontSDK(config),
createClientSessionSDK: (tokenStorage) =>
new SessionStorefrontSDK({ ...config, tokenStorage }),
createServerSessionSDK: (_event, tokenStorage) =>
new SessionStorefrontSDK({ ...config, tokenStorage }),
createServerCookieAdapter: (event) => ({
get: (name) => getCookie(event, name) ?? null,
set: (name, value, opts) => setCookie(event, name, value, opts),
delete: (name) => deleteCookie(event, name),
}),
bootstrapSession: (sdk) => sdk.ensureAccessToken().then(() => {}),
});
// Server API route
export default defineEventHandler(async (event) => {
const sdk = storefront.session(event);
return sdk.customer.getCustomer();
});Astro
import { createSSRFactory } from "@commercengine/ssr-utils";
import {
PublicStorefrontSDK,
SessionStorefrontSDK,
Environment,
} from "@commercengine/storefront-sdk";
import type { AstroCookies } from "astro";
const config = {
storeId: import.meta.env.STORE_ID,
apiKey: import.meta.env.API_KEY,
environment: Environment.Staging,
};
export const storefront = createSSRFactory<
PublicStorefrontSDK,
SessionStorefrontSDK,
AstroCookies
>({
createPublicSDK: () => new PublicStorefrontSDK(config),
createClientSessionSDK: (tokenStorage) =>
new SessionStorefrontSDK({ ...config, tokenStorage }),
createServerSessionSDK: (_cookies, tokenStorage) =>
new SessionStorefrontSDK({ ...config, tokenStorage }),
createServerCookieAdapter: (cookies) => ({
get: (name) => cookies.get(name)?.value ?? null,
set: (name, value, opts) => cookies.set(name, value, opts),
delete: (name) => cookies.delete(name),
}),
bootstrapSession: (sdk) => sdk.ensureAccessToken().then(() => {}),
});SolidStart
import { createSSRFactory } from "@commercengine/ssr-utils";
import {
PublicStorefrontSDK,
SessionStorefrontSDK,
Environment,
} from "@commercengine/storefront-sdk";
import { getCookie, setCookie, deleteCookie, type H3Event } from "vinxi/http";
const config = {
storeId: import.meta.env.VITE_STORE_ID,
apiKey: import.meta.env.VITE_API_KEY,
environment: Environment.Staging,
};
export const storefront = createSSRFactory<
PublicStorefrontSDK,
SessionStorefrontSDK,
H3Event
>({
createPublicSDK: () => new PublicStorefrontSDK(config),
createClientSessionSDK: (tokenStorage) =>
new SessionStorefrontSDK({ ...config, tokenStorage }),
createServerSessionSDK: (_event, tokenStorage) =>
new SessionStorefrontSDK({ ...config, tokenStorage }),
createServerCookieAdapter: (event) => ({
get: (name) => getCookie(event, name) ?? null,
set: (name, value, opts) => setCookie(event, name, value, opts),
delete: (name) => deleteCookie(event, name),
}),
bootstrapSession: (sdk) => sdk.ensureAccessToken().then(() => {}),
});
// In a server function
import { getRequestEvent } from "solid-js/web";
const event = getRequestEvent()!;
const sdk = storefront.session(event);Factory Behavior
| Method | Client | Server |
| ---------------- | ---------------------------------------- | ----------------------------------------- |
| public() | Cached singleton | Cached singleton |
| session() | Cached singleton (ClientTokenStorage) | Throws — context required |
| session(ctx) | Returns cached client singleton (ctx ignored) | Fresh instance (ServerTokenStorage) |
| bootstrap() | Runs bootstrapSession (deduped) | No-op (resolves immediately) |
The factory does not cache server session instances — frameworks layer
their own per-request caching on top (React cache(), SvelteKit
event.locals, Nuxt request context, etc.).
bootstrap() only dedupes concurrent/in-flight calls. It is not permanent
memoization: once a bootstrap run settles, a later call will execute the
bootstrap callback again. That allows flows like logout or session clear to
bootstrap a fresh anonymous session later.
Low-Level API
For manual wiring without the factory:
ServerTokenStorage
Cookie-backed token storage for server request contexts.
import { ServerTokenStorage, type CookieAdapter } from "@commercengine/ssr-utils";
const adapter: CookieAdapter = {
get: (name) => /* framework cookie get */ null,
set: (name, value, options) => { /* framework cookie set */ },
delete: (name) => { /* framework cookie delete */ },
};
const storage = new ServerTokenStorage(adapter, {
prefix: "ce_", // cookie name prefix
maxAge: 2592000, // 30 days
path: "/",
secure: true,
sameSite: "lax",
});ClientTokenStorage
Browser-side token storage backed by document.cookie. Uses the same cookie
key naming convention as ServerTokenStorage so cookies are shared seamlessly
between server and client.
import { ClientTokenStorage } from "@commercengine/ssr-utils";
const storage = new ClientTokenStorage({ prefix: "ce_" });createCookieAdapter
Helper for cookie stores that expose get (returning { value } objects),
set, and delete methods — e.g. Next.js cookies().
import { createCookieAdapter } from "@commercengine/ssr-utils";
import { cookies } from "next/headers";
const adapter = createCookieAdapter(await cookies());Mental Model
- Public SDK — API-key-backed, no session. Safe for build-time, prerender, and static generation.
- Session SDK — cookie-backed session with automatic token lifecycle.
Pass a framework request context on the server; on the client the factory
manages a singleton backed by
document.cookie.
This package intentionally does not provide build-time token caching. Public prerender/build reads should use the public SDK directly.
Related Packages
@commercengine/storefront-sdk— Core storefront SDK@commercengine/storefront— App-facing umbrella with Next.js and TanStack Start wrappers@commercengine/pos— Point of Sale SDK
License
All Rights Reserved
