Extending String prototype with useful methods

JavaScript’s String primitive has a wide variety of methods that manipulate internal state and provide different ways to interface it to your functionality. String helper methods could be extended by creating custom functions that could be used the same way default methods are invoked.
A simple case could be a scenario when you want to use a ‘templating’ functionality without actually relying on third party libraries. The task could be done by just few lines of code like the example below:

/**
 * Implementation of string 'replaceTokens'
 *
 * @remark - replaces all tokens in the form of {x}, {y}, {z}, etc... by the passed map parameters
 *
 * const test = 'Both numbers {one} and {two} are not equal';
 * const map = { one: 1, two: 2 };
 * console.log(test.replaceTokens(map));
 * ---> 'Both numbers 1 and 2 are not equal'
 */
String.prototype.replaceTokens = function() {
  let sourceString = this;
  const [map] = arguments;

  sourceString.replace(/\{(.*?)}/g, function(token, key) {
    sourceString = sourceString.replace(token, map[key]);
  });

  return sourceString;
};

If you are coding it in TypeScript you will probably notice the Property ‘replaceTokens’ does not exist on type ‘String’ error. It’s related to the fact that you are trying to ‘extend’ the String primitive with something that has not been defined yet. The way to resolve the issue is to for example create a string.d.ts file holding the next declaration:

declare interface String {
    replaceTokens: Function;
}

Retry mechanism paradigm with back-off

Probably you already faced a problem when an operation fails and you need to retry it in a certain amount of time or want to try it few more times before giving up and fire an error. A simple solution would be to use functionality similar to the below piece of code:

async function retryFunction(func, timeout = 100, factor = 2, retries = 4) {
  try {
    return await func();
  } catch (err) {
    if (retries < 1) {
      throw err;
    }
    logger.warn(`Retrying function in ${timeout / 1000} seconds`);
    await sleep(timeout);
    return retryFunction(func, timeout * factor, factor, retries - 1);
  }
};

How to convert BigEndian to LittleEndian and vice versa

Operations over multi-byte data types are not common and situations where you need to deal with them are not often. However when the time comes to deal with those types of data some helper functions could come into play. Below you could find all functions potentially needed in order to convert multi-byte data type representations known as BigEndian and LittleEndian:

function convertToBigEndian(val) {
  const buf = Buffer.allocUnsafe(4);

  return buf.writeUInt32BE(val, 0);
}

function convertToLittleEndian(val) {
  const buf = Buffer.allocUnsafe(4);

  return buf.writeUInt32LE(val, 0);
}

function convertToOtherEndian(val) {
  return Buffer.from(val).reverse();
}

Splitting a string into multiple strings with equal length

There are many cases when you need to split a long text, string or any other content into a bunch of chunks with equal length. One of the cases is when you stream a certificate from a remote service and would like to validate a payload. Usually certificates are formatted as long strings without additional starting and ending tags. An example certificate could look like:

MIICEjCCAXsCAg36MA0GCSqGSIb3DQEBBQUAMIGbMQswCQYDVQQGEwJKUDEOMAwGA1UECBMFVG9reW8xEDAOBgNVBAcTB0NodW8ta3UxETAPBgNVBAoTCEZyYW5rNEREMRgwFgYDVQQLEw9XZWJDZXJ0IFN1cHBvcnQxGDAWBgNVBAMTD0ZyYW5rNEREIFdlYiBDQTEjMCEGCSqGSIb3DQEJARYUc3VwcG9ydEBmcmFuazRkZC5jb20wHhcNMTIwODIyMDUyNjU0WhcNMTcwODIxMDUyNjU0WjBKMQswCQYDVQQGEwJKUDEOMAwGA1UECAwFVG9reW8xETAPBgNVBAoMCEZyYW5rNEREMRgwFgYDVQQDDA93d3cuZXhhbXBsZS5jb20wXDANBgkqhkiG9w0BAQEFAANLADBIAkEAm/xmkHmEQrurE/0re/jeFRLl8ZPjBop7uLHhnia7lQG/5zDtZIUC3RVpqDSwBuw/NTweGyuP+o8AG98HxqxTBwIDAQABMA0GCSqGSIb3DQEBBQUAA4GBABS2TLuBeTPmcaTaUW/LCB2NYOy8GMdzR1mx8iBIu2H6/E2tiY3RIevV2OW61qY2/XRQg7YPxx3ffeUugX9F4J/iPnnu1zAxxyBy2VguKv4SWjRFoRkIfIlHX0qVviMhSlNy2ioFLy7JcPZb+v3ftDGywUqcBiVDoea0Hn+GmxZA

In order to format it properly you could perform a regular expression transformation like /.{1,64}/g and string concatenation similar to:

const certificate = `-----BEGIN CERTIFICATE-----\n${publicKey.x5c[0].match(/.{1,64}/g).join('\n')}\n-----END CERTIFICATE-----`;

which will produce the following nice looking certificate

-----BEGIN CERTIFICATE-----
MIICEjCCAXsCAg36MA0GCSqGSIb3DQEBBQUAMIGbMQswCQYDVQQGEwJKUDEOMAwG
A1UECBMFVG9reW8xEDAOBgNVBAcTB0NodW8ta3UxETAPBgNVBAoTCEZyYW5rNERE
MRgwFgYDVQQLEw9XZWJDZXJ0IFN1cHBvcnQxGDAWBgNVBAMTD0ZyYW5rNEREIFdl
YiBDQTEjMCEGCSqGSIb3DQEJARYUc3VwcG9ydEBmcmFuazRkZC5jb20wHhcNMTIw
ODIyMDUyNjU0WhcNMTcwODIxMDUyNjU0WjBKMQswCQYDVQQGEwJKUDEOMAwGA1UE
CAwFVG9reW8xETAPBgNVBAoMCEZyYW5rNEREMRgwFgYDVQQDDA93d3cuZXhhbXBs
ZS5jb20wXDANBgkqhkiG9w0BAQEFAANLADBIAkEAm/xmkHmEQrurE/0re/jeFRLl
8ZPjBop7uLHhnia7lQG/5zDtZIUC3RVpqDSwBuw/NTweGyuP+o8AG98HxqxTBwID
AQABMA0GCSqGSIb3DQEBBQUAA4GBABS2TLuBeTPmcaTaUW/LCB2NYOy8GMdzR1mx
8iBIu2H6/E2tiY3RIevV2OW61qY2/XRQg7YPxx3ffeUugX9F4J/iPnnu1zAxxyBy
2VguKv4SWjRFoRkIfIlHX0qVviMhSlNy2ioFLy7JcPZb+v3ftDGywUqcBiVDoea0
Hn+GmxZA
-----END CERTIFICATE-----

Non-blocking sleep in an asynchronous function

If you would like to sleep the execution for a specific amount of time you could do it by the following ways:

const util = require('util');
const sleep = util.promisify(setTimeout);

or

const sleep = delay => new Promise(resolve => setTimeout(resolve, delay));

then in your code you could simply invoke it as:

await sleep(1000);