Skip to content

Commit 77b66d2

Browse files
Feat: Add helper to encode special characters (@W-17577102@) (#416)
* add encoding helper * update CHANGELOG
1 parent 7c18ea0 commit 77b66d2

File tree

6 files changed

+113
-2
lines changed

6 files changed

+113
-2
lines changed

.eslintrc.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444
"",
4545
{
4646
"pattern": "^ \\* Copyright \\(c\\) \\d{4}, salesforce.com, inc\\.$",
47-
"template": " * Copyright (c) 2022, salesforce.com, inc."
47+
"template": " * Copyright (c) 2025, salesforce.com, inc."
4848
},
4949
" * All rights reserved.",
5050
" * SPDX-License-Identifier: BSD-3-Clause",

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
## CHANGELOG
22

3+
34
## v4.2.0 - future release
5+
6+
### Enchancements
47
- Allow custom params for 'loginGuestUser' and custom body for 'loginRegisteredUserB2C' function [#415](https://github.com/SalesforceCommerceCloud/commerce-sdk/pull/415)
8+
- Add helper to encode special SCAPI characters [#416](https://github.com/SalesforceCommerceCloud/commerce-sdk/pull/416)
59

610
## v4.1.0
711

README.md

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,12 @@ Please be aware that existing tenants are on a temporary allow list and will see
1818

1919
In practice, we recommend that customers using the SLAS helper functions upgrade to `v4.0.0` of the `commerce-sdk`.
2020

21+
## :warning: Planned SDK Changes :warning:
22+
23+
### Encoding path parameters
24+
25+
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.
26+
2127
## Prerequisites
2228

2329
Download and install Node.js and npm [here](https://nodejs.org/en/download/).
@@ -319,6 +325,67 @@ console.log('get response: ', getResponse)
319325
console.log('post response: ', postResponse)
320326
```
321327

328+
### Encoding special characters
329+
330+
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.
331+
332+
Additionally, SCAPI has special characters that should be double encoded, specifically `%` and `,`:
333+
- `%` should always be double encoded
334+
- `,` should be double encoded when used as part of an ID/parameter string, and single encoded when used to differentiate items in a list
335+
336+
There is a helper function called `encodeSCAPISpecialCharacters` that can be utilized to single encode the SCAPI special characters and no other special characters.
337+
338+
Here's an example where the `getCategory/getCategories` endpoints are called with a `categoryID` with special characters:
339+
```javascript
340+
import * as CommerceSdk from "commerce-sdk";
341+
const { helpers, Product } = CommerceSdk;
342+
343+
const clientConfig = {
344+
parameters: {
345+
clientId: "<your-client-id>",
346+
organizationId: "<your-org-id>",
347+
shortCode: "<your-short-code>",
348+
siteId: "<your-site-id>",
349+
}
350+
};
351+
352+
const shopperProducts = new Product.ShopperProducts({
353+
...clientConfig,
354+
headers: {authorization: `Bearer <insert_access_token>`}
355+
});
356+
357+
const categoryId = "SpecialCharacter,%$^@&$;()!123Category";
358+
// "SpecialCharacter%2C%25$^@&$;()!123Category"
359+
const scapiSpecialEncodedId = helpers.encodeSCAPISpecialCharacters(categoryId);
360+
361+
362+
// id is a path parameter for API call:
363+
// <base-url>/product/shopper-products/v1/organizations/{organizationId}/categories/{id}
364+
const categoryResult = await shopperProducts.getCategory({
365+
parameters: {
366+
// Path parameters are NOT encoded by the SDK, so we have to single encode special characters
367+
// and the SCAPI special characters will end up double encoded
368+
id: encodeURIComponent(scapiSpecialEncodedId),
369+
}
370+
});
371+
372+
console.log("categoryResult: ", categoryResult);
373+
374+
// `ids` are a query parameter and comma delimited to separate category IDs
375+
const categoriesResult = await shopperProducts.getCategories({
376+
parameters: {
377+
// No need to use `encodeURIComponent` as query parameters are single encoded by the SDK
378+
// So the SCAPI special characters will end up double encoded as well
379+
// Commas that separate items in a list will end up single encoded
380+
ids: `${scapiSpecialEncodedId},${scapiSpecialEncodedId}`,
381+
}
382+
});
383+
384+
console.log("categoriesResult: ", categoriesResult);
385+
```
386+
387+
**NOTE: In the next major version release, path parameters will be single encoded by default**
388+
322389
## Caching
323390

324391
The SDK currently supports two types of caches - In-memory and Redis. Both the implementations respect [standard cache headers](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control). To use another type of cache, write your own implementation of the [CacheManager](https://github.com/SalesforceCommerceCloud/commerce-sdk-core/tree/main/src/base/cacheManager.ts). See the [default cache manager](https://github.com/SalesforceCommerceCloud/commerce-sdk-core/tree/main/src/base/cacheManagerKeyv.ts) to design your implementation.

src/static/helperTemplates/index.ts.hbs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@
66
*/
77

88
import { callCustomEndpoint } from "./customApi";
9+
import { encodeSCAPISpecialCharacters } from "./fetchHelpers";
910
export const helpers = {
10-
callCustomEndpoint
11+
callCustomEndpoint,
12+
encodeSCAPISpecialCharacters
1113
}
1214
export * as slasHelpers from "./slas";
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/*
2+
* Copyright (c) 2025, salesforce.com, inc.
3+
* All rights reserved.
4+
* SPDX-License-Identifier: BSD-3-Clause
5+
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause
6+
*/
7+
import { encodeSCAPISpecialCharacters } from "./fetchHelpers";
8+
import { expect } from "chai";
9+
10+
describe("encodeSCAPISpecialCharacters", () => {
11+
it("only encodes special characters `%` and `,` in a string", () => {
12+
const input = "women'sCategory,%@#$%^&*()_+,";
13+
const expectedOutput = "women'sCategory%2C%25@#$%25^&*()_+%2C";
14+
const output = encodeSCAPISpecialCharacters(input);
15+
expect(output).to.be.equal(expectedOutput);
16+
});
17+
18+
it("returns the same string if no SCAPI special characters are included", () => {
19+
const input = "women'sCategory!@#$^&*()_+";
20+
const output = encodeSCAPISpecialCharacters(input);
21+
expect(output).to.be.equal(input);
22+
});
23+
});

src/static/helpers/fetchHelpers.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
/*
2+
* Copyright (c) 2025, salesforce.com, inc.
3+
* All rights reserved.
4+
* SPDX-License-Identifier: BSD-3-Clause
5+
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause
6+
*/
7+
8+
/**
9+
* Single encodes SCAPI specific special characters (percentage sign `%` and comma `,`) in the given string in UTF-8
10+
* Does not encode any other special characters in the string
11+
* @param str - The string to encode
12+
* @returns The encoded string
13+
*/
14+
export const encodeSCAPISpecialCharacters = (str: string): string =>
15+
str.replace(/%/g, "%25").replace(/,/g, "%2C");

0 commit comments

Comments
 (0)