diff --git a/packages/extension-chakra-store-locator/README.md b/packages/extension-chakra-store-locator/README.md
index 008f4d9c7d..5b7d39cd9c 100644
--- a/packages/extension-chakra-store-locator/README.md
+++ b/packages/extension-chakra-store-locator/README.md
@@ -35,7 +35,7 @@ If you want to use this without having to install `@chakra-ui` in your project,
### `@salesforce/commerce-sdk-react` Provider
-This extension uses the `@salesforce/commerce-sdk-react` package to fetch the store locator data from SCAPI. Your application must use the `CommerceApiProvider` in the React component tree.
+This extension uses the `@salesforce/commerce-sdk-react` package to fetch the store locator data from SCAPI. If you provide a `commerceApi` configuration in the extension config, the `CommerceApiProvider` will be added to the React component tree as the default provider. If you already have a `CommerceApiProvider` in your application, do not include the `commerceApi` configuration in the extension config.
## Configurations
@@ -66,7 +66,16 @@ The Store Locator extension is configured via the `mobify.app.extensions` proper
"countryCode": "DE",
"countryName": "Germany"
}
- ]
+ ],
+ "commerceApi": {
+ "proxyPath": "/mobify/proxy/api",
+ "parameters": {
+ "shortCode": "8o7m175y",
+ "clientId": "c9c45bfd-0ed3-4aa2-9971-40f88962b836",
+ "organizationId": "f_ecom_zzrf_001",
+ "siteId": "RefArchGlobal"
+ }
+ }
}
]
]
diff --git a/packages/extension-chakra-store-locator/src/components/with-optional-commerce-sdk-react-provider.test.jsx b/packages/extension-chakra-store-locator/src/components/with-optional-commerce-sdk-react-provider.test.jsx
new file mode 100644
index 0000000000..f6d1e7e796
--- /dev/null
+++ b/packages/extension-chakra-store-locator/src/components/with-optional-commerce-sdk-react-provider.test.jsx
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2025, 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
+ */
+import React from 'react'
+import {render, screen} from '@testing-library/react'
+import {withOptionalCommerceSdkReactProvider} from './with-optional-commerce-sdk-react-provider'
+import PropTypes from 'prop-types'
+
+jest.mock('@salesforce/commerce-sdk-react', () => ({
+ useCommerceApi: jest.fn(),
+ // eslint-disable-next-line react/prop-types
+ CommerceApiProvider: ({children}) => {
+ return
+
+/**
+ * Higher-order component that conditionally installs the CommerceApiProvider if the config is provided.
+ *
+ * @param WrappedComponent - The component to be optionally wrapped with CommerceApiProvider.
+ * @param config - The configuration object for the CommerceApiProvider.
+ * @returns A component that wraps the given component with CommerceApiProvider if it is not already present in the component tree.
+ */
+export const withOptionalCommerceSdkReactProvider = (
+ WrappedComponent: React.ComponentType
,
+ config: UserConfig
+) => {
+ const HOC: React.FC
= (props: WithOptionalCommerceSdkReactProvider) => {
+ if (useHasCommerceApiProvider()) {
+ return
+ }
+ if (!config.commerceApi || !config.commerceApi?.parameters) {
+ logger.error(
+ 'CommerceApiProvider is not installed and no commerceApi config is provided, this extension may not work as expected.'
+ )
+ return
+ }
+ const appOrigin = getAppOrigin()
+ return (
+
+
+
+ )
+ }
+
+ return HOC
+}
diff --git a/packages/extension-chakra-store-locator/src/logger.ts b/packages/extension-chakra-store-locator/src/logger.ts
new file mode 100644
index 0000000000..8f30ca05ab
--- /dev/null
+++ b/packages/extension-chakra-store-locator/src/logger.ts
@@ -0,0 +1,9 @@
+/*
+ * Copyright (c) 2025, 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
+ */
+import createLogger from '@salesforce/pwa-kit-runtime/utils/logger-factory'
+
+export const logger = createLogger({packageName: 'extension-chakra-store-locator'})
diff --git a/packages/extension-chakra-store-locator/src/setup-app.ts b/packages/extension-chakra-store-locator/src/setup-app.ts
index f1fb30ed79..34e07c582d 100644
--- a/packages/extension-chakra-store-locator/src/setup-app.ts
+++ b/packages/extension-chakra-store-locator/src/setup-app.ts
@@ -11,13 +11,16 @@ import {RouteProps} from 'react-router-dom'
// Platform Imports
import {ApplicationExtension} from '@salesforce/pwa-kit-extension-sdk/react'
+import {applyHOCs} from '@salesforce/pwa-kit-extension-sdk/react/utils'
// Local Imports
import {withOptionalChakra} from './components/with-optional-chakra-provider'
+import {withOptionalCommerceSdkReactProvider} from './components/with-optional-commerce-sdk-react-provider'
import {withStoreLocator} from './components/with-store-locator'
import {Config} from './types'
import StoreLocatorPage from './pages/store-locator'
+import {logger} from './logger'
import extensionMeta from '../extension-meta.json'
class StoreLocatorExtension extends ApplicationExtension {
@@ -29,13 +32,19 @@ class StoreLocatorExtension extends ApplicationExtension {
const config = this.getConfig()
if (!config.supportedCountries || config.supportedCountries.length === 0) {
- // TODO: use our logger
- console.warn(
+ logger.error(
'[extension-chakra-store-locator] Missing supportedCountries, this extension will not work.'
)
}
- return withStoreLocator(withOptionalChakra(App), config)
+ const HOCs = [
+ (component: React.ComponentType) => withStoreLocator(component, config),
+ (component: React.ComponentType) =>
+ withOptionalCommerceSdkReactProvider(component, config),
+ (component: React.ComponentType) => withOptionalChakra(component)
+ ]
+
+ return applyHOCs(App, HOCs)
}
extendRoutes(routes: RouteProps[]): RouteProps[] {
diff --git a/packages/extension-chakra-store-locator/src/types/config.ts b/packages/extension-chakra-store-locator/src/types/config.ts
index 192cf1e9ed..68f5e41af3 100644
--- a/packages/extension-chakra-store-locator/src/types/config.ts
+++ b/packages/extension-chakra-store-locator/src/types/config.ts
@@ -21,6 +21,17 @@ export interface UserConfig extends ApplicationExtensionConfig {
countryCode: string
countryName: string
}>
+ commerceApi?: {
+ proxyPath: string
+ parameters: {
+ shortCode: string
+ clientId: string
+ organizationId: string
+ siteId: string
+ locale: string
+ currency: string
+ }
+ }
}
/**
diff --git a/packages/template-typescript-minimal/package.json b/packages/template-typescript-minimal/package.json
index 7708e8dde5..cf67e317ed 100644
--- a/packages/template-typescript-minimal/package.json
+++ b/packages/template-typescript-minimal/package.json
@@ -22,6 +22,7 @@
"@emotion/react": "^11.13.3",
"@emotion/styled": "^11.13.0",
"@loadable/component": "^5.15.3",
+ "@salesforce/extension-chakra-store-locator": "^0.1.0-extensibility-preview.3",
"@salesforce/pwa-kit-dev": "4.0.0-extensibility-preview.3",
"@salesforce/pwa-kit-extension-sdk": "4.0.0-extensibility-preview.3",
"@salesforce/pwa-kit-react-sdk": "4.0.0-extensibility-preview.3",
@@ -44,6 +45,44 @@
"npm": "^8.0.0 || ^9.0.0 || ^10.0.0"
},
"mobify": {
+ "app": {
+ "extensions": [
+ [
+ "@salesforce/extension-chakra-store-locator",
+ {
+ "enabled": true,
+ "path": "/store-locator",
+ "radius": 100,
+ "radiusUnit": "km",
+ "defaultPageSize": 10,
+ "defaultPostalCode": "10178",
+ "defaultCountry": "Germany",
+ "defaultCountryCode": "DE",
+ "supportedCountries": [
+ {
+ "countryCode": "US",
+ "countryName": "United States"
+ },
+ {
+ "countryCode": "DE",
+ "countryName": "Germany"
+ }
+ ],
+ "commerceApi": {
+ "proxyPath": "/mobify/proxy/api",
+ "parameters": {
+ "shortCode": "8o7m175y",
+ "clientId": "c9c45bfd-0ed3-4aa2-9971-40f88962b836",
+ "organizationId": "f_ecom_zzrf_001",
+ "siteId": "RefArchGlobal",
+ "locale": "en-GB",
+ "currency": "USD"
+ }
+ }
+ }
+ ]
+ ]
+ },
"ssrEnabled": true,
"ssrOnly": [
"ssr.js",