Skip to content

Instantly share code, notes, and snippets.

@hnestmann
Created December 2, 2020 07:23
Show Gist options
  • Save hnestmann/349885908d77b2c6a48c2692dbffce33 to your computer and use it in GitHub Desktop.
Save hnestmann/349885908d77b2c6a48c2692dbffce33 to your computer and use it in GitHub Desktop.
const { appendFile } = require("fs");
const fetch = require("node-fetch");
const fs = require('fs');
const params = JSON.parse(fs.readFileSync('./config.json'));
/* Example
{
"accountManager": {
"scope": "SALESFORCE_COMMERCE_API:xxxx_xxx sfcc.yy",
"clientId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"secret": "xXxXxxx"
},
"shopperProductSearchApi": {
"siteId": "xxx",
"searchTerm": "shoe",
"shortCode": "xxxx",
"organizationId": "f_ecom_xxx"
}
}
*/
const startTimeStamp = (new Date()).toISOString().replace(/[^a-zA-Z0-9]/g, "");
/**
* Logs a message to a file and optionally to console
*/
function log(message) {
if (!fs.existsSync('./logs/')) {
fs.mkdirSync('./logs/', 0744);
}
const logFileName = `./logs/${startTimeStamp}.log`
fs.appendFileSync(logFileName, message + '\n');
if (params.execution.verbose) {
console.info((new Date()).toISOString() + ': ' + message)
}
}
/**
* Searches enabled customers email address for a given search term and allows paging controls
*/
async function searchProducts(searchTerm, start, limit) {
log(`searching ${limit} products from point ${start}`);
const url = `https://${params.shopperProductSearchApi.shortCode}.api.commercecloud.salesforce.com/search/shopper-search/v1/organizations/${params.shopperProductSearchApi.organizationId}/product-search?q=${searchTerm}&siteId=${params.shopperProductSearchApi.siteId}`;
var token = await getAuthenticationToken();
const response = await fetch(url, {
method: 'get',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${token}`
}
});
const searchResponseDocument = await response.json();
return searchResponseDocument;
}
var expiration = new Date(0);
var token;
/**
* Gets the authentication token and generates a new one if timed out
*/
async function getAuthenticationToken() {
const url = `https://${params.shopperProductSearchApi.shortCode}.api.commercecloud.salesforce.com/customer/shopper-customers/v1/organizations/${params.shopperProductSearchApi.organizationId}/customers/actions/login?siteId=${params.shopperProductSearchApi.siteId}&clientId=${params.accountManager.clientId}`;
if (expiration.getTime() < Date.now() || !token) {
log('fetching new jwt')
const searchParams = JSON.stringify({
"type" : "guest"
})
const authString = `${params.accountManager.clientId}:${params.accountManager.secret}`;
const buff = Buffer.from(authString, 'utf-8');
const b64AuthString = buff.toString('base64');
const response = await fetch(url, {
method: 'post',
body: searchParams,
headers: {
'Content-Type': 'application/json',
'Authorization': `Basic ${b64AuthString}`
},
});
const json = await response.json();
// the locally held token will expire a minute before the actual
expiration = new Date(Date.now() + ((30*60) - 60) * 1000);
token = response.headers.get('authorization').replace('Bearer ','');
}
return token;
};
/**
* The main 'controller' - externalized as async function
*/
async function mainAsync() {
var productsInitial = await searchProducts(params.shopperProductSearchApi.searchTerm, 0, 1);
log(`processing ${JSON.stringify(productsInitial.total)} products`);
var pages = Math.ceil(productsInitial.total / 25);
for (let i = 0; i <= pages; i++) {
let start = Date.now();
let products = await searchProducts(params.shopperProductSearchApi.searchTerm, i * 25, 25);
log(`page ${i} time ${Date.now() - start}`);
}
}
mainAsync();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment