Skip to content

sfcc API

Everything the package exports, by the path you import it from. Open an export for its signature and options.

@evolve-framework/sfcc

The SFCC client and its configuration (SFCC_*), the request and store context, and the dataloaders.

Classes

ClientContextA storefront client's Salesforce Commerce Cloud session: the federated token it carries, whether that token is a signed-in customer's, and the client to call SFCC as the token's holder (getClient).
import { ClientContext } from "@evolve-framework/sfcc";
new ClientContext(storeContext: StoreContext, loader: ClientContextLoader, token?: FederatedToken)
OptionTypeDescription
getSystemRequestBuilder() => Promise<Client>
createClient(token: FederatedToken) => Promise<UserClient>
MethodDescription
setAccessToken(token: string): void
getProductProjectionParams(): ProductProjectionQueryArgs
hasToken(): boolean
isAuthenticated(): boolean
setCommercetoolsToken(token: TokenInfo): void
getClient(): Promise<UserClient>Return the active request builder using the client credentials, so the all requests will be made as the client (with their scopes)
load(): Promise<void>Load the customer information.
ClientContextLoaderThe loader for the client context.
import { ClientContextLoader } from "@evolve-framework/sfcc";
new ClientContextLoader(endpoint: string, clientFactory: ClientFactoryInterface)
OptionTypeDescription
getSystemRequestBuilder() => Promise<Client>
getUserRequestBuilder(token: FederatedToken) => UserClient
MethodDescription
createClient(token: FederatedToken): Promise<UserClient>
getSystemRequestBuilder(): Promise<Client>
ClientFactoryCreates SFCC clients: one system client, signed in once and cached, and a user client per federated token.
import { ClientFactory } from "@evolve-framework/sfcc";
new ClientFactory(options?: ClientFactoryOptions)
OptionTypeDescription
clientIdstring
siteIdstring
organizationIdstring
shortCodestring
clientSecret?string
scopes?string[]
MethodDescription
configure(options: ClientFactoryOptions): void
reconfigure(options?: ClientFactoryOptions | undefined): void
getSystemClient(): Promise<Client>
getSystemRequestBuilder(): Promise<Client>
getUserRequestBuilder(token: FederatedToken): UserClient
CommerceCloudConfigThe Salesforce Commerce Cloud instance a service talks to, through a SLAS client.
import { CommerceCloudConfig } from "@evolve-framework/sfcc";

Extends BaseConfig

new CommerceCloudConfig()
StoreContextThe store context indicates the current storefront context.
import { StoreContext } from "@evolve-framework/sfcc";
new StoreContext(args: StoreContextArgs, client: Client)
OptionTypeDescription
storeKeystring
localestring
currencystring

Functions

fromAddressThe contract's Address as an SFCC order address.
import { fromAddress } from "@evolve-framework/sfcc";
function fromAddress(addr: Address): OrderAddress
OptionTypeDescription
countrystring

The country where the address is located. Must be provided.

postalCodestring

The postal code or ZIP code for the address, depending on the country.

__typename?"Address"
additionalAddressInfo?Maybe<string>

Extra information regarding the address, such as building number, floor, or apartment number.

city?Maybe<string>

The city where the address is located.

company?Maybe<string>

The company name for business addresses. This field may be omitted for personal addresses.

email?Maybe<string>

The email address for contact, optional for both personal and business addresses.

familyName?Maybe<string>

The family name (last name) of the individual. May be left empty for company addresses.

givenName?Maybe<string>

The given name (first name) of the individual. May be left empty for company addresses.

id?Maybe<string>
name?Maybe<string>

What the owner calls this address in their address book, such as "Work" or the name of a company location. Empty when the address was never named.

phone?Maybe<string>

The phone number associated with this address, typically including the international code.

region?Maybe<string>

The region, state, or province for the address. Used to represent subdivisions of countries.

salutation?Maybe<SalutationType>

The salutation or title for the person associated with the address.

streetAddress?Maybe<string>

The unstructured full street address, including street name, number, and optional suffix.

streetName?Maybe<string>

The name of the street where the address is located.

streetNumber?Maybe<string>

The number of the building on the street. This field represents the main address number.

streetNumberSuffix?Maybe<string>

Additional suffixes to the street number, often used in countries like the Netherlands. Example: "A", "B", or "1/2".

Returns ShopperBasketsTypes.OrderAddress

getClientOptionsThe ClientFactory options, read from the SFCC_* config values.
import { getClientOptions } from "@evolve-framework/sfcc";
function getClientOptions(config: Config): Promise<ClientFactoryOptions>
OptionTypeDescription
SFCC_CLIENT_IDstring
SFCC_CLIENT_SECRETstring
SFCC_ORGANIZATION_IDstring
SFCC_SHORT_CODEstring
SFCC_SITE_IDstring

Returns Promise<ClientFactoryOptions>

toAddressAn SFCC order address as the contract's Address.
import { toAddress } from "@evolve-framework/sfcc";
function toAddress(addr: OrderAddress): Address

Returns Address

Constants

sfccDataLoadersThe loaders every sfcc module contributes.
import { sfccDataLoaders } from "@evolve-framework/sfcc";
const sfccDataLoaders: DataLoaderDefinition<SfccLoaderContext, { categoryById: DataLoader<string, Category | null, string>; customerById: DataLoader<string, Customer | null, string>; …

Types

CartResultA Cart as a resolver returns it, before its field resolvers fill the rest.
import { type CartResult } from "@evolve-framework/sfcc";
export type CartResult = MakeOptional<WithInternalFields<Cart>, "availablePaymentMethods" | "discountCodes" | "availableShippingMethods" | "lineItems">;
ClientContextInfoThe signed-in customer, as the client context keeps it.
import { type ClientContextInfo } from "@evolve-framework/sfcc";
export type ClientContextInfo = {
id: string;
familyName: string;
givenName: string;
email: string;
};
CommerceCloudBasket
import { type CommerceCloudBasket } from "@evolve-framework/sfcc";
export type CommerceCloudBasket = ShopperBasketsV2Types.Basket;
CommerceCloudBasketProductItem
import { type CommerceCloudBasketProductItem } from "@evolve-framework/sfcc";
export type CommerceCloudBasketProductItem = ShopperBasketsV2Types.ProductItem;
CommerceCloudCategory
import { type CommerceCloudCategory } from "@evolve-framework/sfcc";
export type CommerceCloudCategory = ShopperProductsTypes.Category;
CommerceCloudCustomer
import { type CommerceCloudCustomer } from "@evolve-framework/sfcc";
export type CommerceCloudCustomer = ShopperCustomersTypes.Customer;
CommerceCloudOrder
import { type CommerceCloudOrder } from "@evolve-framework/sfcc";
export type CommerceCloudOrder = ShopperOrdersTypes.Order;
CommerceCloudOrderProductItem
import { type CommerceCloudOrderProductItem } from "@evolve-framework/sfcc";
export type CommerceCloudOrderProductItem = ShopperOrdersTypes.ProductItem;
CommerceCloudProduct
import { type CommerceCloudProduct } from "@evolve-framework/sfcc";
export type CommerceCloudProduct = ShopperProductsTypes.Product;
CommerceCloudVariant
import { type CommerceCloudVariant } from "@evolve-framework/sfcc";
export type CommerceCloudVariant = ShopperProductsTypes.Variant;
ContextValueWhat resolvers read: the service's context plus the modules' loaders.
import { type ContextValue } from "@evolve-framework/sfcc";
type ContextValue$1 = RequestContextValue & {
loaders: DataLoaders;
};
DataLoadersThe data loaders of one request, by name.
import { type DataLoaders } from "@evolve-framework/sfcc";
export type DataLoaders = {
categoryById: ReturnType<typeof createCategoryByIdLoader>;
customerById: ReturnType<typeof createCustomerByIdLoader>;
orderByOrderNumber: ReturnType<typeof createOrderByOrderNumberLoader>;
productById: ReturnType<typeof createProductByIdLoader>;
productSlugsById: ReturnType<typeof createProductSlugsByIdLoader>;
};
ProductBaseFieldsA Product as a resolver returns it, before its field resolvers fill the rest.
import { type ProductBaseFields } from "@evolve-framework/sfcc";
export type ProductBaseFields = MakeOptional<WithInternalFields<Product>, "categories" | "localizedSlugs" | "primaryCategory" | "startingPrice" | "variant" | "variants" | "variantDimensions">;
ProductCategoryBaseFieldsA ProductCategory as a resolver returns it, before its field resolvers fill the rest.
import { type ProductCategoryBaseFields } from "@evolve-framework/sfcc";
export type ProductCategoryBaseFields = MakeOptional<WithInternalFields<ProductCategory>, "ancestors" | "children">;
ProductVariantInstanceThe SFCC product and variant a ProductVariant is resolved from.
import { type ProductVariantInstance } from "@evolve-framework/sfcc";
export type ProductVariantInstance = {
product: CommerceCloudProduct;
variant: CommerceCloudVariant;
};
ProductVariantResultA ProductVariant as a resolver returns it, before its field resolvers fill the rest.
import { type ProductVariantResult } from "@evolve-framework/sfcc";
export type ProductVariantResult = MakeOptional<WithInternalFields<ProductVariant>, "specifications" | "product">;
RequestBuilderAn SFCC client signed in with the service's own client credentials.
import { type RequestBuilder } from "@evolve-framework/sfcc";
export type RequestBuilder = Client;
RequestContextValueThe part of the context the service builds per request.
import { type RequestContextValue } from "@evolve-framework/sfcc";

Split out from ContextValue because loaders is contributed by the modules, not by the service: a context factory returns this, and Application merges the modules' loader declarations onto it. Splitting the type is what makes that expressible — Omit<ContextValue, "loaders"> does not work here, since the base context carries an index signature and Omit then keeps only that, silently dropping every named property.

export type RequestContextValue = ContextValue & {
log: typeof logger;
storeContext: StoreContext;
clientContext: ClientContext$1;
federatedToken?: FederatedToken;
clientFactory: ClientFactory;
globalScopedClient: () => RequestBuilder;
config: Record<string, unknown>;
request: RequestWithIP;
};
SfccLoaderContextWhat these loaders read off the request context.
import { type SfccLoaderContext } from "@evolve-framework/sfcc";

clientContext is required here, where the hand-rolled createDataLoaders below has to take it as optional and throw on use: a module declaring this type cannot be composed into a service that does not provide one, so the check moved from the first read of a loader to the line composing the modules. It also has to be the very instance the useClientContext plugin loads the federated token into, which is why the service owns it.

export type SfccLoaderContext = {
clientFactory: ClientFactory;
storeContext: StoreContext;
clientContext: ClientContext;
};
TokenInfoAn SFCC session's tokens and when its access token expires.
import { type TokenInfo } from "@evolve-framework/sfcc";
export type TokenInfo = {
subject: string;
refreshToken?: string;
accessToken: string;
expiresAt: number;
};
UserRequestBuilderAn SFCC client that calls as the shopper, with the federated token's SFCC access token.
import { type UserRequestBuilder } from "@evolve-framework/sfcc";
export type UserRequestBuilder = UserClient;

@evolve-framework/sfcc/auth

Shopper login and the token manager behind guest and registered sessions.

Classes

RefreshTokenExpiredErrorThrown when SFCC no longer accepts the refresh token.
import { RefreshTokenExpiredError } from "@evolve-framework/sfcc/auth";

Extends Error

new RefreshTokenExpiredError()
TokenManagerManages SFCC OAuth2 tokens via the ShopperLogin SDK client.
import { TokenManager } from "@evolve-framework/sfcc/auth";

Service-specific authentication flows (e.g. PKCE customer login) live in the consuming service. They can call transformTokenResponse to convert their own SDK responses into TokenInfo.

new TokenManager()
MethodDescription
configure(options: TokenManagerOptions): void
createCustomerSession( email: string, password: string, usid: string | undefined, ): Promise<TokenInfo>
createAnonymousSession(): Promise<TokenInfo>
refreshAccessToken(refreshToken: string): Promise<TokenInfo>
logout( token: string, type: "access_token" | "refresh_token", ): Promise<boolean>
transformTokenResponse( tokenResponse: TokenResponse, sessionType: SessionType, ): TokenInfoConvert a raw SDK token response into a normalised TokenInfo.

Functions

getTokenManagerOptionsThe TokenManager options, read from the SFCC_* config values.
import { getTokenManagerOptions } from "@evolve-framework/sfcc/auth";
function getTokenManagerOptions(config: Config): Promise<TokenManagerOptions>
OptionTypeDescription
SFCC_CLIENT_IDstring
SFCC_SITE_IDstring
SFCC_ORGANIZATION_IDstring
SFCC_SHORT_CODEstring
SFCC_CLIENT_SECRET?string

Returns Promise<TokenManagerOptions>

setAuthenticatedUserSigns the customer in and puts the session's tokens on the federated token.
import { setAuthenticatedUser } from "@evolve-framework/sfcc/auth";
function setAuthenticatedUser(
tokenManager: TokenManager,
options: AuthenticatedUserArgs,
): Promise<void>
OptionTypeDescription
clientContextClientContext$1
emailstring
passwordstring
storeKeystring

Returns Promise<void>

setTokenPuts an SFCC session's tokens on the federated token, and loads the customer when the session is a signed-in one.
import { setToken } from "@evolve-framework/sfcc/auth";
function setToken(
clientContext: ClientContext$1,
token: TokenInfo,
): Promise<void>
OptionTypeDescription
subjectstring
accessTokenstring
expiresAtnumber
refreshToken?string

Returns Promise<void>

Types

SessionTypeThe kind of session a token belongs to, carried at the front of its refresh token.
import { type SessionType } from "@evolve-framework/sfcc/auth";
export type SessionType = "customer" | "anonymous" | "refresh";
TokenManagerOptionsThe SFCC client the TokenManager signs in with.
import { type TokenManagerOptions } from "@evolve-framework/sfcc/auth";
export type TokenManagerOptions = {
clientId: string;
clientSecret?: string;
siteId: string;
organizationId: string;
shortCode: string;
};

@evolve-framework/sfcc/dataloaders

The request-scoped dataloaders for products, categories, customers and orders.

Functions

createCategoryByIdLoaderCategories by id, in the store's locale; cached for five minutes.
import { createCategoryByIdLoader } from "@evolve-framework/sfcc/dataloaders";
function createCategoryByIdLoader(
clientFactory: ClientFactory,
storeContext: StoreContext,
): DataLoader<string, CommerceCloudCategory | null, string>

Returns DataLoader<string, CommerceCloudCategory | null, string>

createCustomerByIdLoaderLoad a customer by their id.
import { createCustomerByIdLoader } from "@evolve-framework/sfcc/dataloaders";
function createCustomerByIdLoader(
clientFactory: ClientFactory,
): DataLoader<string, CommerceCloudCustomer | null>

Returns DataLoader<string, CommerceCloudCustomer | null>

createDataLoadersBuilds the loaders from their inputs directly, for tests and for services that have not handed loader assembly over to the modules yet.
import { createDataLoaders } from "@evolve-framework/sfcc/dataloaders";
function createDataLoaders(
clientFactory: ClientFactory,
storeContext: StoreContext,
clientContext?: ClientContext$1,
): DataLoaders

Returns DataLoaders

createOrderByOrderNumberLoaderThe shopper's orders by order number, read one at a time.
import { createOrderByOrderNumberLoader } from "@evolve-framework/sfcc/dataloaders";
function createOrderByOrderNumberLoader(
storeContext: StoreContext,
clientContext: ClientContext$1,
): DataLoader<string, CommerceCloudOrder | null>

Returns DataLoader<string, CommerceCloudOrder | null>

createProductByIdLoaderProducts by id, in the store's locale, read with the system client.
import { createProductByIdLoader } from "@evolve-framework/sfcc/dataloaders";
function createProductByIdLoader(
clientFactory: ClientFactory,
storeContext: StoreContext,
clientContext: ClientContext$1,
): DataLoader<string, ShopperProductsTypes.Product | null>

Returns DataLoader<string, ShopperProductsTypes.Product | null>

createProductSlugsByIdLoaderA product's slug per locale, by product id, for the alternate URLs of its detail page.
import { createProductSlugsByIdLoader } from "@evolve-framework/sfcc/dataloaders";
function createProductSlugsByIdLoader(
storeContext: StoreContext,
): DataLoader<string, ProductSlugs | null>

Returns DataLoader<string, ProductSlugs | null>

Constants

sfccDataLoadersThe loaders every sfcc module contributes.
import { sfccDataLoaders } from "@evolve-framework/sfcc/dataloaders";
const sfccDataLoaders: DataLoaderDefinition<SfccLoaderContext, { categoryById: DataLoader<string, Category | null, string>; customerById: DataLoader<string, Customer | null, string>; …

Types

DataLoadersThe data loaders of one request, by name.
import { type DataLoaders } from "@evolve-framework/sfcc/dataloaders";
export type DataLoaders = {
categoryById: ReturnType<typeof createCategoryByIdLoader>;
customerById: ReturnType<typeof createCustomerByIdLoader>;
orderByOrderNumber: ReturnType<typeof createOrderByOrderNumberLoader>;
productById: ReturnType<typeof createProductByIdLoader>;
productSlugsById: ReturnType<typeof createProductSlugsByIdLoader>;
};
SfccLoaderContextWhat these loaders read off the request context.
import { type SfccLoaderContext } from "@evolve-framework/sfcc/dataloaders";

clientContext is required here, where the hand-rolled createDataLoaders below has to take it as optional and throw on use: a module declaring this type cannot be composed into a service that does not provide one, so the check moved from the first read of a loader to the line composing the modules. It also has to be the very instance the useClientContext plugin loads the federated token into, which is why the service owns it.

export type SfccLoaderContext = {
clientFactory: ClientFactory;
storeContext: StoreContext;
clientContext: ClientContext;
};

@evolve-framework/sfcc/modules

The modules: auth, business units, cart, catalog, checkout, customers, orders, order approvals, payments, quotes and shopping lists.

Classes

AuthModuleSign-in for Salesforce Commerce Cloud: login, logout and token refresh, and the session routes a storefront calls before it has a token.
import { AuthModule } from "@evolve-framework/sfcc/modules";

Extends AbstractModule<SfccLoaderContext>

new AuthModule(options: { config: AuthModuleConfig; clientFactory: ClientFactory; })
OptionTypeDescription
configAuthModuleConfig

The SLAS client, site, organization and short code that guest and customer tokens are requested from, refreshed with and revoked against.

clientFactoryClientFactory

The client POST /api/client-context reads the signed-in customer through, as that customer.

BusinessUnitModuleThe B2B company account part of the contract.
import { BusinessUnitModule } from "@evolve-framework/sfcc/modules";

Extends AbstractModule<SfccLoaderContext>

new BusinessUnitModule()
CartModuleThe active basket on Salesforce Commerce Cloud: cart, creating one, adding, updating and removing lines, discount codes, and the available payment and shipping methods.
import { CartModule } from "@evolve-framework/sfcc/modules";

Extends AbstractModule<SfccLoaderContext>

new CartModule()
CatalogModuleThe catalog on Salesforce Commerce Cloud: products by id, slug or SKU, categories, a category page by its path, and productSearch, answered by the Shopper Search API.
import { CatalogModule } from "@evolve-framework/sfcc/modules";

Extends AbstractModule<SfccLoaderContext>

new CatalogModule(options: { clientFactory: ClientFactory; })
OptionTypeDescription
clientFactoryClientFactory

The system client productSearch, categories and productSearchSuggestions query the catalog through.

CheckoutModulePlacing an order on Salesforce Commerce Cloud: orderPlace.
import { CheckoutModule } from "@evolve-framework/sfcc/modules";

Extends AbstractModule<SfccLoaderContext>

new CheckoutModule()
CustomerModuleThe signed-in shopper on Salesforce Commerce Cloud: customer and customerExists.
import { CustomerModule } from "@evolve-framework/sfcc/modules";

Extends AbstractModule<SfccLoaderContext>

new CustomerModule()
OrderApprovalModuleThe order-approval part of the contract on an engine without approvals, so a B2B storefront's schema is complete: queues and rules are empty, every decision or rule change is refused with a typed error, and approval on an order or a placement is null.
import { OrderApprovalModule } from "@evolve-framework/sfcc/modules";

Extends AbstractModule<SfccLoaderContext>

new OrderApprovalModule()
OrderModuleA shopper's placed orders on Salesforce Commerce Cloud: the order and orders fields on a customer.
import { OrderModule } from "@evolve-framework/sfcc/modules";

Extends AbstractModule<SfccLoaderContext>

new OrderModule()
PaymentModulePaying on Salesforce Commerce Cloud: paymentCreate and Apple Pay merchant validation.
import { PaymentModule } from "@evolve-framework/sfcc/modules";

Extends AbstractModule<SfccLoaderContext>

new PaymentModule()
QuoteModuleThe quote part of the contract with no resolvers: Commerce Cloud has no quotes, and composing this keeps a B2B storefront's schema complete.
import { QuoteModule } from "@evolve-framework/sfcc/modules";

Extends AbstractModule<SfccLoaderContext>

new QuoteModule()
ShoppingListModuleThe shopping list part of the contract, not yet backed by Commerce Cloud: reading a list answers nothing, and creating, updating and deleting a list or its lines answer "Not implemented yet".
import { ShoppingListModule } from "@evolve-framework/sfcc/modules";

Extends AbstractModule<SfccLoaderContext>

new ShoppingListModule()

Types

AuthModuleConfigThe SFCC_* config values AuthModule signs in with.
import { type AuthModuleConfig } from "@evolve-framework/sfcc/modules";
export interface AuthModuleConfig {
SFCC_CLIENT_ID: string;
SFCC_CLIENT_SECRET?: string;
SFCC_SITE_ID: string;
SFCC_ORGANIZATION_ID: string;
SFCC_SHORT_CODE: string;
}