An open API service indexing awesome lists of open source software.

https://github.com/salesforcecommercecloud/commerce-sdk-isomorphic

Browser & Node.js JavaScript client for B2C Commerce API
https://github.com/salesforcecommercecloud/commerce-sdk-isomorphic

Last synced: about 2 months ago
JSON representation

Browser & Node.js JavaScript client for B2C Commerce API

Awesome Lists containing this project

README

          

# commerce-sdk-isomorphic

This SDK provides a Browser & Node.js JavaScript client for calling [B2C Commerce Shopper APIs](https://developer.salesforce.com/docs/commerce/commerce-api/overview).

_For a Node.js only SDK that can also access Admin APIs checkout [Commerce SDK](https://github.com/SalesforceCommerceCloud/commerce-sdk)._

## Documentation

An auto-generated [documentation site](https://salesforcecommercecloud.github.io/commerce-sdk-isomorphic/) provides comprehensive reference for all available endpoints and types across API classes. Following the v4.0.0 release, the underlying SDK file structure has been reorganized, introducing additional layers of imports/exports that may affect navigation.

### Navigating the Documentation

**For API Classes:**

1. **Accessing API Classes:** Click on the API class name (e.g., `shopperProducts`) on the right hand side
2. **Viewing Endpoints:** Scroll to the `Classes` section and click the corresponding API class link (e.g., `ShopperProducts`) to see available endpoints and their parameters
3. **Type Definitions:** Scroll to the `Type aliases` section for available types

**Utility Classes:** Utility classes and methods such as `clientConfig` and `helpers` maintain the same structure as previous versions.

**NOTES:**

1. **Type Access**: API class types are accessible through the `Types` namespace (e.g., `ShopperProductsTypes`). Individual types can be accessed as `ShopperProductsTypes.Product`.

2. **Type References**: The `References` section under API classes in the generated documentation may show duplicate entries. This occurs because types are exported both at their original definition and under the API class namespace. Both references point to the same underlying type definition.

## :warning: Planned API Changes :warning:

### Shopper Context

Starting July 31st 2024, all endpoints in the Shopper context API will require the `siteId` parameter for new customers. This field is marked as optional for backward compatibility and will be changed to mandatory tentatively by January 2025. You can read more about the planned change [here](https://developer.salesforce.com/docs/commerce/commerce-api/references/shopper-context?meta=Summary) in the notes section.

### Shopper Login (SLAS)

SLAS will soon require new tenants to pass `channel_id` as an argument for retrieving guest access tokens. You can read more about the planned change [here](https://developer.salesforce.com/docs/commerce/commerce-api/guide/slas.html#guest-tokens).

Please be aware that existing tenants are on a temporary allow list and will see no immediate disruption to service. We do ask that all users seek to adhere to the `channel_id` requirement before the end of August to enhance your security posture before the holiday peak season.

In practice, we recommend:

- For customers using the SLAS helpers with a public client, it is recommended to upgrade to at least `v1.8.0` of the `commerce-sdk-isomorphic`.
- For customers using the SLAS helpers with a private client, it is recommended to upgrade to `v3.0.0` of the `commerce-sdk-isomorphic`.

## :warning: Planned SDK Changes :warning:

### Encoding path parameters

In the next major version release, the SDK will encode special characters (UTF-8 based on SCAPI guidelines) in path parameters by default. Please see the [Encoding special characters](#encoding-special-characters) section for more details.

## Getting Started

### Requirements

- Node `^20.x` or `^22.x`
- The SDK requires B2C Commerce API (SCAPI) to be configured. For more info see [Getting started with SCAPI](https://developer.salesforce.com/docs/commerce/commerce-api/guide/get-started.html).

### Installation

```bash
# This package uses yarn, if you don't have yarn:
# npm install -g yarn
yarn install commerce-sdk-isomorphic
```

### Usage

```javascript
import {helpers, ShopperLogin, ShopperSearch} from 'commerce-sdk-isomorphic';

const config = {
// SCAPI does not support CORS, so client side requests must use a reverse proxy.
proxy: 'https://localhost:3000',
parameters: {
clientId: '',
organizationId: '',
shortCode: '',
siteId: '',
},
};

const {access_token} = await helpers.loginGuestUser({
slasClient: new ShopperLogin(config),
parameters: {redirectURI: `${config.proxy}/callback`}
});

const shopperSearch = new ShopperSearch({
...config,
headers: {authorization: `Bearer ${access_token}`},
});

const searchResult = await shopperSearch.productSearch({
parameters: {q: 'shirt'},
});
```

#### Fetch Options

You can configure how the SDK makes requests using the `fetchOptions` parameter. It is passed to [node-fetch](https://github.com/node-fetch/node-fetch/1#api) on the server and [whatwg-fetch](https://github.github.io/fetch/) on browser.

```javascript
const https = require("https");

const config = {
fetchOptions: {
// By default, requests made using the SDK do not include cookies.
credentials: "include",
timeout: 2000,
agent: new https.agent({ keepAlive: true }),
},
};
```

For more info, refer to the [documentation site](https://salesforcecommercecloud.github.io/commerce-sdk-isomorphic/).

#### `throwOnBadResponse`

When `true`, the SDK throws an `Error` on responses whose status is not 2xx or 304. By default, the value of this flag is `false` for backwards compatibility. Below is an example for accessing the error object via `e.response.json()`.

```js
const config = {
throwOnBadResponse: true
// rest of the config object...
};

const shopperSearch = new ShopperSearch({
...config
});

// in an async function
try {
const searchResult = await shopperSearch.productSearch({
parameters: { q: "shirt" },
});
} catch (e) {
const error = await e.response.json();
console.log(error);
// error is the JSON object - {error: ",,,"}
}
```

#### Additional Config Settings

* `headers`: Headers to include with API requests.

#### Custom Query Parameters

You can pass custom query parameters through the SDK to be used in [B2C Commerce API Hooks](https://developer.salesforce.com/docs/commerce/commerce-api/guide/extensibility_via_hooks.html). Custom query parameters must begin with `c_`:

```javascript
const searchResult = await shopperSearch.productSearch({
parameters: {
q: 'shirt',
c_paramkey: ''
},
});
```

Invalid query parameters that are not a part of the API and do not follow the `c_` custom query parameter convention are filtered from the request with a warning.

#### Custom APIs

The SDK supports calling [B2C Commerce Custom APIs](https://developer.salesforce.com/docs/commerce/commerce-api/guide/custom-apis.html) with a helper function, `callCustomEndpoint`:

```javascript
import pkg from "commerce-sdk-isomorphic";
const { helpers } = pkg;

const clientConfig = {
parameters: {
clientId: "",
organizationId: "",
shortCode: "",
siteId: "",
},
// If not provided, it'll use the default production URI:
// 'https://{shortCode}.api.commercecloud.salesforce.com/custom/{apiName}/{apiVersion}'
// path parameters should be wrapped in curly braces like the default production URI
baseUri: "",
};

// Required params: apiName, endpointPath, shortCode, organizaitonId
// Required path params can be passed into:
// options.customApiPathParameters or clientConfig.parameters
const customApiPathParameters = {
apiName: "loyalty-info",
apiVersion: "v1", // defaults to v1 if not provided
endpointPath: "customers",
};

const accessToken = "";

await helpers.callCustomEndpoint({
options: {
method: "GET",
parameters: {
queryParameter: "queryParameter1",
},
headers: {
// Content-Type is defaulted to application/json if not provided
"Content-Type": "application/json",
authorization: `Bearer ${accessToken}`,
},
customApiPathParameters,
},
clientConfig,
});

await helpers.callCustomEndpoint({
options: {
method: "POST",
parameters: {
queryParameter: "queryParameter1",
},
headers: {
authorization: `Bearer ${accessToken}`,
},
customApiPathParameters,
body: JSON.stringify({ data: "data" }),
},
clientConfig,
});
```

For more documentation about this helper function, please refer to the [commerce-sdk-isomorphic docs](https://salesforcecommercecloud.github.io/commerce-sdk-isomorphic/modules/helpers.html).

#### Custom Fetch function

You can provide your own custom fetch function to intercept, log, or modify all SDK requests. This is useful for:
- **Request/Response Logging**: Track all API calls for debugging and monitoring
- **Request Interception**: Add custom headers, modify request URLs, or implement custom retry logic
- **Error Handling**: Add custom error processing or transformation before responses reach your application
- **Performance Monitoring**: Measure request/response times and track API performance metrics

**Example with Logging:**
```javascript
// Custom fetch function with detailed logging
const customFetch = async (url, options) => {
console.log(`[SDK Request] ${options?.method || 'GET'} ${url}`);
console.log('[SDK Request Headers]', options?.headers);
if (options?.body) {
console.log('[SDK Request Body]', options.body);
}

const startTime = Date.now();
const response = await fetch(url, options);
const duration = Date.now() - startTime;

console.log(`[SDK Response] ${response.status} ${response.statusText} (${duration}ms)`);
console.log('[SDK Response Headers]', Object.fromEntries(response.headers.entries()));

return response;
};

const config = {
parameters: {
clientId: '',
organizationId: '',
shortCode: '',
siteId: '',
},
fetch: customFetch,
};
```

#### Encoding special characters

The SDK currently single encodes special characters for query parameters in UTF-8 format based on SCAPI guidelines. However, the SDK does NOT encode path parameters, and will require the developer to encode any path parameters with special characters.

Additionally, SCAPI has special characters that should be double encoded, specifically `%` and `,`:
- `%` should always be double encoded
- `,` should be double encoded when used as part of an ID/parameter string, and single encoded when used to differentiate items in a list

There is a helper function called `encodeSCAPISpecialCharacters` that can be utilized to single encode the SCAPI special characters and no other special characters.

Here's an example where the `getCategory/getCategories` endpoints are called with a `categoryID` with special characters:
```javascript
import pkg from "commerce-sdk-isomorphic";
const { helpers, ShopperProducts } = pkg;

const clientConfig = {
parameters: {
clientId: "",
organizationId: "",
shortCode: "",
siteId: "",
}
};

const shopperProducts = new ShopperProducts({
...clientConfig,
headers: {authorization: `Bearer `}
});

const categoryId = "SpecialCharacter,%$^@&$;()!123Category";
// "SpecialCharacter%2C%25$^@&$;()!123Category"
const scapiSpecialEncodedId = helpers.encodeSCAPISpecialCharacters(categoryId);

// id is a path parameter for API call:
// /product/shopper-products/v1/organizations/{organizationId}/categories/{id}
const categoryResult = await shopperProducts.getCategory({
parameters: {
// No need to use `encodeURIComponent` as query parameters are single encoded by the SDK
// So the SCAPI special characters will end up double encoded as well
id: scapiSpecialEncodedId,
}
});

console.log("categoryResult: ", categoryResult);

// `ids` are a query parameter and comma delimited to separate category IDs
const categoriesResult = await shopperProducts.getCategories({
parameters: {
// No need to use `encodeURIComponent` as query parameters are single encoded by the SDK
// So the SCAPI special characters will end up double encoded as well
// Commas that separate items in a list will end up single encoded
ids: `${scapiSpecialEncodedId},${scapiSpecialEncodedId}`,
}
});

console.log("categoriesResult: ", categoriesResult);
```

**NOTE: In the next major version release, path parameters will be single encoded by default**

## License Information

The Commerce SDK Isomorphic is licensed under BSD-3-Clause license. See the [license](./LICENSE.txt) for details.