Skip to content

Commit 26a7ccb

Browse files
Feat: Add helper to encode special characters (@W-17577102@) (#189)
* add initial fix * switch order of CI * add helper to encode special char * revert encoding path params * bump bundle size
1 parent 4031a4a commit 26a7ccb

File tree

6 files changed

+97
-5
lines changed

6 files changed

+97
-5
lines changed

.github/workflows/test.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ jobs:
1919
with:
2020
node-version: ${{ matrix.node }}
2121
cache: npm
22+
- run: yarn install
2223
- name: Cache node modules
2324
id: cache-nodemodules
2425
uses: actions/cache@v3
@@ -27,7 +28,6 @@ jobs:
2728
with:
2829
path: "**/node_modules"
2930
key: ${{ runner.os }}-node${{ matrix.node }}-build-${{ env.cache-name }}-${{ hashFiles('yarn.lock') }}
30-
- run: yarn install
3131
if: ${{ steps.cache-nodemodules.outputs.cache-hit != 'true' }}
3232
- run: yarn run renderTemplates
3333
- run: yarn build:lib

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
## v3.3.0
44
- Allow custom params for 'loginGuestUser', 'authorizeIDP' and custom body for 'loginRegisteredUserB2C' functions [#186](https://github.com/SalesforceCommerceCloud/commerce-sdk-isomorphic/pull/186)
5+
- Add helper to encode special SCAPI characters [#189](https://github.com/SalesforceCommerceCloud/commerce-sdk-isomorphic/pull/189)
56

67
## v3.2.0
78

README.md

Lines changed: 69 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,12 @@ In practice, we recommend:
2121
- 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`.
2222
- For customers using the SLAS helpers with a private client, it is recommended to upgrade to `v3.0.0` of the `commerce-sdk-isomorphic`.
2323

24+
## :warning: Planned SDK Changes :warning:
25+
26+
### Encoding path parameters
27+
28+
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.
29+
2430
## Getting Started
2531

2632
### Requirements
@@ -114,7 +120,7 @@ try {
114120

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

117-
### Custom Query Parameters
123+
#### Custom Query Parameters
118124

119125
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_`:
120126

@@ -129,7 +135,7 @@ const searchResult = await shopperSearch.productSearch({
129135

130136
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.
131137

132-
### Custom APIs
138+
#### Custom APIs
133139

134140
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`:
135141

@@ -195,6 +201,67 @@ await helpers.callCustomEndpoint({
195201

196202
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).
197203

204+
#### Encoding special characters
205+
206+
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.
207+
208+
Additionally, SCAPI has special characters that should be double encoded, specifically `%` and `,`:
209+
- `%` should always be double encoded
210+
- `,` should be double encoded when used as part of an ID/parameter string, and single encoded when used to differentiate items in a list
211+
212+
There is a helper function called `encodeSCAPISpecialCharacters` that can be utilized to single encode the SCAPI special characters and no other special characters.
213+
214+
Here's an example where the `getCategory/getCategories` endpoints are called with a `categoryID` with special characters:
215+
```javascript
216+
import pkg from "commerce-sdk-isomorphic";
217+
const { helpers, ShopperProducts } = pkg;
218+
219+
const clientConfig = {
220+
parameters: {
221+
clientId: "<your-client-id>",
222+
organizationId: "<your-org-id>",
223+
shortCode: "<your-short-code>",
224+
siteId: "<your-site-id>",
225+
}
226+
};
227+
228+
const shopperProducts = new ShopperProducts({
229+
...clientConfig,
230+
headers: {authorization: `Bearer <insert_access_token>`}
231+
});
232+
233+
const categoryId = "SpecialCharacter,%$^@&$;()!123Category";
234+
// "SpecialCharacter%2C%25$^@&$;()!123Category"
235+
const scapiSpecialEncodedId = helpers.encodeSCAPISpecialCharacters(categoryId);
236+
237+
238+
// id is a path parameter for API call:
239+
// <base-url>/product/shopper-products/v1/organizations/{organizationId}/categories/{id}
240+
const categoryResult = await shopperProducts.getCategory({
241+
parameters: {
242+
// Path parameters are NOT encoded by the SDK, so we have to single encode special characters
243+
// and the SCAPI special characters will end up double encoded
244+
id: encodeURIComponent(scapiSpecialEncodedId),
245+
}
246+
});
247+
248+
console.log("categoryResult: ", categoryResult);
249+
250+
// `ids` are a query parameter and comma delimited to separate category IDs
251+
const categoriesResult = await shopperProducts.getCategories({
252+
parameters: {
253+
// No need to use `encodeURIComponent` as query parameters are single encoded by the SDK
254+
// So the SCAPI special characters will end up double encoded as well
255+
// Commas that separate items in a list will end up single encoded
256+
ids: `${scapiSpecialEncodedId},${scapiSpecialEncodedId}`,
257+
}
258+
});
259+
260+
console.log("categoriesResult: ", categoriesResult);
261+
```
262+
263+
**NOTE: In the next major version release, path parameters will be single encoded by default**
264+
198265
## License Information
199266

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

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@
181181
},
182182
{
183183
"path": "commerce-sdk-isomorphic-with-deps.tgz",
184-
"maxSize": "561 kB"
184+
"maxSize": "562 kB"
185185
}
186186
],
187187
"proxy": "https://SHORTCODE.api.commercecloud.salesforce.com"

src/static/helpers/fetchHelper.test.ts

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import nock from 'nock';
88
import {Response} from 'node-fetch';
99
import * as environment from './environment';
1010
import ClientConfig from '../clientConfig';
11-
import {doFetch} from './fetchHelper';
11+
import {doFetch, encodeSCAPISpecialCharacters} from './fetchHelper';
1212

1313
describe('doFetch', () => {
1414
const basePath = 'https://short_code.api.commercecloud.salesforce.com';
@@ -139,3 +139,18 @@ describe('doFetch', () => {
139139
);
140140
});
141141
});
142+
143+
describe('encodeSCAPISpecialCharacters', () => {
144+
test('only encodes special characters `%` and `,` in a string', () => {
145+
const input = "women'sCategory,%@#$%^&*()_+,";
146+
const expectedOutput = "women'sCategory%2C%25@#$%25^&*()_+%2C";
147+
const output = encodeSCAPISpecialCharacters(input);
148+
expect(output).toEqual(expectedOutput);
149+
});
150+
151+
test('returns the same string if no SCAPI special characters are included', () => {
152+
const input = "women'sCategory!@#$^&*()_+";
153+
const output = encodeSCAPISpecialCharacters(input);
154+
expect(output).toEqual(input);
155+
});
156+
});

src/static/helpers/fetchHelper.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,3 +68,12 @@ export const doFetch = async <Params extends BaseUriParameters>(
6868
return (text ? JSON.parse(text) : {}) as unknown | Response;
6969
}
7070
};
71+
72+
/**
73+
* Single encodes SCAPI specific special characters (percentage sign `%` and comma `,`) in the given string in UTF-8
74+
* Does not encode any other special characters in the string
75+
* @param str - The string to encode
76+
* @returns The encoded string
77+
*/
78+
export const encodeSCAPISpecialCharacters = (str: string): string =>
79+
str.replace(/%/g, '%25').replace(/,/g, '%2C');

0 commit comments

Comments
 (0)