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;
}

Create a self-signed TLS certificate for your local development

When you are developing an applicaiton on your localhost and want to access and test it through a secure connection you will need a certificate. Requesting one from a 3rd party service will cost you money, so here is the way to create a self-signed certificate by yourself. Bear in mind you could use it only for testing purposes and will not be able to validate it against 3rd party authorities.

1. Create the certificate by issuing the followig line:

openssl req -new -newkey rsa:4096 -x509 -sha256 -days 365 -nodes -out public.crt -keyout private.key

Once executed the command will lead you through a set of questions in order to generate the certificate as requested. You will be presented with a screen similar to the one below:

Country Name (2 letter code) [AU]:
State or Province Name (full name) [Some-State]:
Locality Name (eg, city) []:
Organization Name (eg, company) [Internet Widgits Pty Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:
Email Address []:

2. Secure the private key:

chmod 400 private.key

As a result of the above commands two files will be generated in your current folder: the public certificate and the related private key.

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-----

How to create a hotfix

If you follow the Semantic Versioning notation when delivering your code it’s important to know the way to create a hotfix when needed. Here are the basic steps to follow in order to achieve it:

  1. Get the latest changes from your remote
    • git fetch
  2. Checkout the version you would like to patch with the hotfix (ex.: “v1.2.3”)
    • git checkout VERSION
  3. Create the hotfix branch for the related version. It should follow the semver convention (ex.: “v1.2.3-1”)
    • git checkout -b hotfix/HOTFIXVERSION
  4. Do your modifications, cherry-pick, apply patches, etc.
  5. Commit your changes
    • git add .
    • git commit -m “fix: The commit message comes here”
  6. Push them to the remote
    • git push -u origin hotfix/HOTFIXVERSION
  7. Tag the hotfix version and push
    • git tag HOTFIXVERSION
    • git push origin HOTFIXVERSION

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);

Squashing multiple commits into one

In your daily tasks if you need to squash multiple commits into one with a custom message just perform the following commands:

git reset --soft HEAD~n # where n is the number of last commits you want to squash into one

git commit --amend

git push -f

another (interactive) way is to use rebase like below:

git rebase -i HEAD~n

the last n commit messages will appear in your text editor. You will see something similar to:

pick 0123456 Message 1
pick 1234567 Message 2
pick 2345678 Message 3

you could just pick the first commit and squash the rest like that:

p 0123456 Message 1
s 1234567 Message 2
s 2345678 Message 3