Skip to content
Merged
1 change: 1 addition & 0 deletions packages/commerce-sdk-react/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
## v5.1.0-dev
- Add Page Designer Support [#3727](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/3727)
- Bump commerce-sdk-isomorphic to 5.1.0 [#3725](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/3725)
- Update ShopperBasketsV2 hooks documentation and query keys
- Add Node 24 support. Drop Node 16 support. [#3652](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/3652)
- Add Shopper Consents API support [#3674](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/3674)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ export const cacheUpdateMatrix: CacheUpdateMatrix<Client> = {
],
remove: [
// We want to fuzzy match all queryKeys with `basketId` in their path
// [`/commerce-sdk-react,/organizations/,${organization},/baskets/,${basketId}`]
// [`/commerce-sdk-react,/organizations/,${organization},/baskets/v2/,${basketId}`]
{queryKey: getBasket.path(parameters)}
]
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {cacheUpdateMatrix} from './cache'
import {ShopperBasketsMutations as mutations} from './mutation'
import * as queries from './query'

describe('Shopper Baskets hooks', () => {
describe('Shopper Baskets V2 hooks', () => {
test('all endpoints have hooks', () => {
// unimplemented = SDK method exists, but no query hook or value in mutations enum
const unimplemented = getUnimplementedEndpoints(ShopperBasketsV2, queries, mutations)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2023, Salesforce, Inc.
* Copyright (c) 2026, Salesforce, Inc.
* All rights reserved.
* SPDX-License-Identifier: BSD-3-Clause
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ const emptyResponseTestCases = [
// Most test cases only apply to non-empty response test cases, some (error handling) can include deleteBasket
const allTestCases = [...nonEmptyResponseTestCases, ...emptyResponseTestCases]

describe('ShopperBaskets mutations', () => {
describe('ShopperBasketsV2 mutations', () => {
const storedCustomerIdKey = `customer_id_${DEFAULT_TEST_CONFIG.siteId}`
beforeAll(() => {
// Make sure we don't accidentally overwrite something before setting up our test state
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ const CLIENT_KEY = CLIENT_KEYS.SHOPPER_BASKETS_V2
type Client = NonNullable<ApiClients[typeof CLIENT_KEY]>

/**
* Mutations available for Shopper Baskets.
* @group ShopperBaskets
* Mutations available for Shopper Baskets V2.
* @group ShopperBasketsV2
* @category Mutation
* @enum
*/
Expand Down Expand Up @@ -165,16 +165,16 @@ export const ShopperBasketsMutations = {
} as const

/**
* Type for Shopper Baskets Mutation.
* @group ShopperBaskets
* Type for Shopper Baskets V2 Mutation.
* @group ShopperBasketsV2
* @category Mutation
*/
export type ShopperBasketsMutation =
(typeof ShopperBasketsMutations)[keyof typeof ShopperBasketsMutations]

/**
* Mutation hook for Shopper Baskets.
* @group ShopperBaskets
* Mutation hook for Shopper Baskets V2.
* @group ShopperBasketsV2
* @category Mutation
*/
export function useShopperBasketsMutation<Mutation extends ShopperBasketsMutation>(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ const testMap: TestMap = {
}
// Type assertion is necessary because `Object.entries` is limited
const testCases = Object.entries(testMap) as Array<[keyof TestMap, TestMap[keyof TestMap]]>
describe('Shopper Baskets query hooks', () => {
describe('Shopper Baskets V2 query hooks', () => {
beforeEach(() => nock.cleanAll())
afterEach(() => {
expect(nock.pendingMocks()).toHaveLength(0)
Expand Down
20 changes: 10 additions & 10 deletions packages/commerce-sdk-react/src/hooks/ShopperBasketsV2/query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@ type Client = NonNullable<ApiClients[typeof CLIENT_KEY]>

/**
* Gets a basket.
* @group ShopperBaskets
* @group ShopperBasketsV2
* @category Query
* @parameter apiOptions - Options to pass through to `commerce-sdk-isomorphic`, with `null` accepted for unset API parameters.
* @parameter queryOptions - TanStack Query query options, with `enabled` by default set to check that all required API parameters have been set.
* @returns A TanStack Query query hook with data from the Shopper Baskets `getBasket` endpoint.
* @returns A TanStack Query query hook with data from the Shopper Baskets V2 `getBasket` endpoint.
* @see {@link https://developer.salesforce.com/docs/commerce/commerce-api/references/shopper-baskets?meta=getBasket| Salesforce Developer Center} for more information about the API endpoint.
* @see {@link https://salesforcecommercecloud.github.io/commerce-sdk-isomorphic/classes/shopperbaskets.shopperbaskets-1.html#getbasket | `commerce-sdk-isomorphic` documentation} for more information on the parameters and returned data type.
* @see {@link https://tanstack.com/query/latest/docs/react/reference/useQuery | TanStack Query `useQuery` reference} for more information about the return value.
Expand Down Expand Up @@ -63,11 +63,11 @@ export const useBasket = (
}
/**
* Gets applicable payment methods for an existing basket considering the open payment amount only.
* @group ShopperBaskets
* @group ShopperBasketsV2
* @category Query
* @parameter apiOptions - Options to pass through to `commerce-sdk-isomorphic`, with `null` accepted for unset API parameters.
* @parameter queryOptions - TanStack Query query options, with `enabled` by default set to check that all required API parameters have been set.
* @returns A TanStack Query query hook with data from the Shopper Baskets `getPaymentMethodsForBasket` endpoint.
* @returns A TanStack Query query hook with data from the Shopper Baskets V2 `getPaymentMethodsForBasket` endpoint.
* @see {@link https://developer.salesforce.com/docs/commerce/commerce-api/references/shopper-baskets?meta=getPaymentMethodsForBasket| Salesforce Developer Center} for more information about the API endpoint.
* @see {@link https://salesforcecommercecloud.github.io/commerce-sdk-isomorphic/classes/shopperbaskets.shopperbaskets-1.html#getpaymentmethodsforbasket | `commerce-sdk-isomorphic` documentation} for more information on the parameters and returned data type.
* @see {@link https://tanstack.com/query/latest/docs/react/reference/useQuery | TanStack Query `useQuery` reference} for more information about the return value.
Expand Down Expand Up @@ -108,11 +108,11 @@ export const usePaymentMethodsForBasket = (
}
/**
* Gets applicable price books for an existing basket.
* @group ShopperBaskets
* @group ShopperBasketsV2
* @category Query
* @parameter apiOptions - Options to pass through to `commerce-sdk-isomorphic`, with `null` accepted for unset API parameters.
* @parameter queryOptions - TanStack Query query options, with `enabled` by default set to check that all required API parameters have been set.
* @returns A TanStack Query query hook with data from the Shopper Baskets `getPriceBooksForBasket` endpoint.
* @returns A TanStack Query query hook with data from the Shopper Baskets V2 `getPriceBooksForBasket` endpoint.
* @see {@link https://developer.salesforce.com/docs/commerce/commerce-api/references/shopper-baskets?meta=getPriceBooksForBasket| Salesforce Developer Center} for more information about the API endpoint.
* @see {@link https://salesforcecommercecloud.github.io/commerce-sdk-isomorphic/classes/shopperbaskets.shopperbaskets-1.html#getpricebooksforbasket | `commerce-sdk-isomorphic` documentation} for more information on the parameters and returned data type.
* @see {@link https://tanstack.com/query/latest/docs/react/reference/useQuery | TanStack Query `useQuery` reference} for more information about the return value.
Expand Down Expand Up @@ -153,11 +153,11 @@ export const usePriceBooksForBasket = (
}
/**
* Gets the applicable shipping methods for a certain shipment of a basket.
* @group ShopperBaskets
* @group ShopperBasketsV2
* @category Query
* @parameter apiOptions - Options to pass through to `commerce-sdk-isomorphic`, with `null` accepted for unset API parameters.
* @parameter queryOptions - TanStack Query query options, with `enabled` by default set to check that all required API parameters have been set.
* @returns A TanStack Query query hook with data from the Shopper Baskets `getShippingMethodsForShipment` endpoint.
* @returns A TanStack Query query hook with data from the Shopper Baskets V2 `getShippingMethodsForShipment` endpoint.
* @see {@link https://developer.salesforce.com/docs/commerce/commerce-api/references/shopper-baskets?meta=getShippingMethodsForShipment| Salesforce Developer Center} for more information about the API endpoint.
* @see {@link https://salesforcecommercecloud.github.io/commerce-sdk-isomorphic/classes/shopperbaskets.shopperbaskets-1.html#getshippingmethodsforshipment | `commerce-sdk-isomorphic` documentation} for more information on the parameters and returned data type.
* @see {@link https://tanstack.com/query/latest/docs/react/reference/useQuery | TanStack Query `useQuery` reference} for more information about the return value.
Expand Down Expand Up @@ -198,11 +198,11 @@ export const useShippingMethodsForShipment = (
}
/**
* This method gives you the external taxation data set by the PUT taxes API. This endpoint can be called only if external taxation mode was used for basket creation. See POST /baskets for more information.
* @group ShopperBaskets
* @group ShopperBasketsV2
* @category Query
* @parameter apiOptions - Options to pass through to `commerce-sdk-isomorphic`, with `null` accepted for unset API parameters.
* @parameter queryOptions - TanStack Query query options, with `enabled` by default set to check that all required API parameters have been set.
* @returns A TanStack Query query hook with data from the Shopper Baskets `getTaxesFromBasket` endpoint.
* @returns A TanStack Query query hook with data from the Shopper Baskets V2 `getTaxesFromBasket` endpoint.
* @see {@link https://developer.salesforce.com/docs/commerce/commerce-api/references/shopper-baskets?meta=getTaxesFromBasket| Salesforce Developer Center} for more information about the API endpoint.
* @see {@link https://salesforcecommercecloud.github.io/commerce-sdk-isomorphic/classes/shopperbaskets.shopperbaskets-1.html#gettaxesfrombasket | `commerce-sdk-isomorphic` documentation} for more information on the parameters and returned data type.
* @see {@link https://tanstack.com/query/latest/docs/react/reference/useQuery | TanStack Query `useQuery` reference} for more information about the return value.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,15 @@ export type QueryKeys = {
'/commerce-sdk-react',
'/organizations/',
string | undefined,
'/baskets/',
'/baskets/v2/',
string | undefined,
Params<'getBasket'>
]
getPaymentMethodsForBasket: [
'/commerce-sdk-react',
'/organizations/',
string | undefined,
'/baskets/',
'/baskets/v2/',
string | undefined,
'/payment-methods',
Params<'getPaymentMethodsForBasket'>
Expand All @@ -33,7 +33,7 @@ export type QueryKeys = {
'/commerce-sdk-react',
'/organizations/',
string | undefined,
'/baskets/',
'/baskets/v2/',
string | undefined,
'/price-books',
Params<'getPriceBooksForBasket'>
Expand All @@ -42,7 +42,7 @@ export type QueryKeys = {
'/commerce-sdk-react',
'/organizations/',
string | undefined,
'/baskets/',
'/baskets/v2/',
string | undefined,
'/shipments/',
string | undefined,
Expand All @@ -53,7 +53,7 @@ export type QueryKeys = {
'/commerce-sdk-react',
'/organizations/',
string | undefined,
'/baskets/',
'/baskets/v2/',
string | undefined,
'/taxes',
Params<'getTaxesFromBasket'>
Expand All @@ -74,7 +74,7 @@ export const getBasket: QueryKeyHelper<'getBasket'> = {
'/commerce-sdk-react',
'/organizations/',
params?.organizationId,
'/baskets/',
'/baskets/v2/',
params?.basketId
],
queryKey: (params: Params<'getBasket'>) => {
Expand All @@ -90,7 +90,7 @@ export const getPaymentMethodsForBasket: QueryKeyHelper<'getPaymentMethodsForBas
'/commerce-sdk-react',
'/organizations/',
params?.organizationId,
'/baskets/',
'/baskets/v2/',
params?.basketId,
'/payment-methods'
],
Expand All @@ -107,7 +107,7 @@ export const getPriceBooksForBasket: QueryKeyHelper<'getPriceBooksForBasket'> =
'/commerce-sdk-react',
'/organizations/',
params?.organizationId,
'/baskets/',
'/baskets/v2/',
params?.basketId,
'/price-books'
],
Expand All @@ -124,7 +124,7 @@ export const getShippingMethodsForShipment: QueryKeyHelper<'getShippingMethodsFo
'/commerce-sdk-react',
'/organizations/',
params?.organizationId,
'/baskets/',
'/baskets/v2/',
params?.basketId,
'/shipments/',
params?.shipmentId,
Expand All @@ -143,7 +143,7 @@ export const getTaxesFromBasket: QueryKeyHelper<'getTaxesFromBasket'> = {
'/commerce-sdk-react',
'/organizations/',
params?.organizationId,
'/baskets/',
'/baskets/v2/',
params?.basketId,
'/taxes'
],
Expand Down
2 changes: 1 addition & 1 deletion packages/pwa-kit-create-app/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
## v3.17.0-dev
- Add Salesforce Payments configuration to generated projects
- Add Salesforce Payments configuration to generated projects [#3725] (https://github.com/SalesforceCommerceCloud/pwa-kit/pull/3725)
- Clear verdaccio npm cache during project generation [#3652](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/3652)
- Add Node 24 support, remove legacy `url` module import. Drop Node 16 support [#3652](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/3652)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -160,10 +160,9 @@ module.exports = {
// Salesforce Payments configuration
// Set enabled to true to enable Salesforce Payments (requires the Salesforce Payments feature toggle to be enabled on the Commerce Cloud instance).
// Set enabled to false to disable Salesforce Payments on the storefront (the Commerce Cloud feature toggle is unaffected).
// sdkUrl and metadataUrl are hosted on your Commerce Cloud instance. Replace <hostname> with your instance hostname.
// This may be a demandware.net hostname (e.g., myinstance.unified.demandware.net) or a vanity/custom hostname.
// sdkUrl: 'https://<hostname>/on/demandware.static/Sites-Site/-/-/internal/jscript/sfp/v1/sfp.js'
// metadataUrl: 'https://<hostname>/on/demandware.static/Sites-Site/-/-/internal/metadata/v1.json'
// Set the sdkUrl and metadataUrl values to point to your Commerce Cloud instance host by replacing the [bm_or_vanity_host] placeholder with your Business Manager or vanity URL host name.
// sdkUrl: 'https://[bm_or_vanity_host]/on/demandware.static/Sites-Site/-/-/internal/jscript/sfp/v1/sfp.js'
// metadataUrl: 'https://[bm_or_vanity_host]/on/demandware.static/Sites-Site/-/-/internal/metadata/v1.json'
sfPayments: {
enabled: false,
sdkUrl: '',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,14 @@ const options = {
port: 3000,

// The protocol on which the development Express app listens.
// Set DEV_SERVER_PROTOCOL to 'https' for HTTPS; defaults to 'http' when unset.
// Note that http://localhost is treated as a secure context for development,
// except by Safari.
protocol: 'http',
protocol: process.env.DEV_SERVER_PROTOCOL || 'http',

// Optional. Path to SSL certificate (.pem) for HTTPS development. Typically a
// self-signed cert for localhost; set DEV_SERVER_SSL_FILE_PATH when using https.
sslFilePath: process.env.DEV_SERVER_SSL_FILE_PATH,

// Option for whether to set up a special endpoint for handling
// private SLAS clients
Expand Down Expand Up @@ -346,7 +351,9 @@ const {handler} = runtime.createHandler(options, (app) => {
// Default source for product images - replace with your CDN
'*.commercecloud.salesforce.com',
'*.demandware.net',
'*.adyen.com' // Payment gateways
'*.adyen.com', // Payment gateways
'pay.google.com', // Google Pay payment handler icon
'www.gstatic.com' // optional, if icon is on gstatic
],
'script-src': [
// Used by the service worker in /worker/main.js
Expand All @@ -373,13 +380,20 @@ const {handler} = runtime.createHandler(options, (app) => {
// Connect to SCRT2 URLs
'*.salesforce-scrt.com',
// Payment gateways
// Note: Google Pay requires different CSP entries depending on the integration and environment.
// - 'pay.google.com' and 'payments.google.com' are generally needed for the SDK to load and create payment tokens.
// - 'google.com/pay/' and 'www.google.com/pay/' may be required for certain flows (especially with Adyen) or in some browsers
// where the interactive payment sheet makes server calls directly to google.com/pay.
// - You may need to adjust these URLs based on your environments.
'*.demandware.net', // Used to load a valid payment scripts in test environment
'*.adyen.com',
'*.paypal.com',
'pay.google.com',
'payments.google.com',
'google.com',
'www.google.com'
'google.com/pay',
'google.com/pay/',

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

are these both needed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added them based on what I saw in the browser for CSP errors

Copy link
Contributor

@vmarta vmarta Mar 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When specifying a path for the CSP header, a trailing slash is significant. It means like matching the any requests that start with this path.

https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Content-Security-Policy?authuser=0#host-source

Paths that end in / match any path they are a prefix of. For example:
example.com/api/ will permit resources from example.com/api/users/new.

Paths that do not end in / are matched exactly. For example:
https://example.com/file.js permits resources from https://example.com/file.js but not https://example.com/file.js/file2.js.

So I'm guessing google.com/pay/ is sufficient, unless there's a request specifically for exactly google.com/pay.

'www.google.com/pay',
'www.google.com/pay/'

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess same question. Do we need www. and google.com? Just want to confirm.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added them based on what I saw in the browser for CSP errors. It would help if someone else can run the checks during our testing phase or locally. We initially had *.google.com which is not safe but google pay seems to be depending on several url patterns

],
'frame-src': [
// Allow frames from Salesforce site.com (Needed for MIAW)
Expand Down
Loading
Loading