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)| Option | Type | Description |
|---|---|---|
getSystemRequestBuilder | () => Promise<Client> | |
createClient | (token: FederatedToken) => Promise<UserClient> |
| Method | Description |
|---|---|
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)| Option | Type | Description |
|---|---|---|
getSystemRequestBuilder | () => Promise<Client> | |
getUserRequestBuilder | (token: FederatedToken) => UserClient |
| Method | Description |
|---|---|
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)| Option | Type | Description |
|---|---|---|
clientId | string | |
siteId | string | |
organizationId | string | |
shortCode | string | |
clientSecret? | string | |
scopes? | string[] |
| Method | Description |
|---|---|
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)| Option | Type | Description |
|---|---|---|
storeKey | string | |
locale | string | |
currency | string |
Functions
fromAddressThe contract's Address as an SFCC order address.
import { fromAddress } from "@evolve-framework/sfcc";function fromAddress(addr: Address): OrderAddress| Option | Type | Description |
|---|---|---|
country | string | The country where the address is located. Must be provided. |
postalCode | string | 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>| Option | Type | Description |
|---|---|---|
SFCC_CLIENT_ID | string | |
SFCC_CLIENT_SECRET | string | |
SFCC_ORGANIZATION_ID | string | |
SFCC_SHORT_CODE | string | |
SFCC_SITE_ID | string |
Returns Promise<ClientFactoryOptions>
toAddressAn SFCC order address as the contract's Address.
import { toAddress } from "@evolve-framework/sfcc";function toAddress(addr: OrderAddress): AddressReturns 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()| Method | Description |
|---|---|
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,
): TokenInfo | Convert 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>| Option | Type | Description |
|---|---|---|
SFCC_CLIENT_ID | string | |
SFCC_SITE_ID | string | |
SFCC_ORGANIZATION_ID | string | |
SFCC_SHORT_CODE | string | |
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>| Option | Type | Description |
|---|---|---|
clientContext | ClientContext$1 | |
email | string | |
password | string | |
storeKey | string |
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>| Option | Type | Description |
|---|---|---|
subject | string | |
accessToken | string | |
expiresAt | number | |
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,): DataLoadersReturns 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; })| Option | Type | Description |
|---|---|---|
config | AuthModuleConfig | The SLAS client, site, organization and short code that guest and customer tokens are requested from, refreshed with and revoked against. |
clientFactory | ClientFactory | The client |
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; })| Option | Type | Description |
|---|---|---|
clientFactory | ClientFactory | The system client |
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;}
