How it works...

The algorithmic heavy lifting is performed by our dependency hsl-to-rgb-for-reals. This is often the case in the landscape of Node's ecosystem. Many fundamental computer science problems have already been solved (often multiple times) by third-party contributors.

Our index.js exports a single function the hsl function. This function applies sanity to the inputs (like rotating 360 degrees back to 0 and enforcing minimum and maximums) and then converts the output from decimal values to hex values, prefixing them with a hash (#).

Since the hsl-to-rgb-for-reals module returns an array of values between 0 and 255, we can use the native map method to iterate over each element in the array and convert it from base 10 to base 16. Then, we join the resulting array into a string.

In our quick command line checks, we call the node binary with the -p flag. This simply evaluates a supplied expression and outputs its value. In each case, the expression involves calling require.

The require function is central to Node's module system; when it's called, the module system performs a series of steps.

First, require has to locate the module according to the supplied argument. Depending on the input, the module may be a local file, a core module, or a separately installed module.

We supplied a path, './', so the function attempts to load the current directory as a module. In order to do this, it looks for a package.json file, and looks up the main field in the package.json file. The main field in our package.json file is index.js, so require recognizes this file as the module's entry point. In the absence of a package.json file or main field, require also defaults to index.js as the entry point.

Once an entry point file has been identified, Node synchronously loads it into a string. The module code is wrapped with the following:

(function (exports, require, module, __filename, __dirname) {
/* module code here */
})

The resulting string is passed through the vm module's runInThisContext method, which essentially tells the JavaScript engine to compile the string into a function. This function is then called with the five parameters dictated in the wrapper (exports, require, module, __filename, and __dirname). The exports argument is an empty object, and the module argument is an object with an exports property pointing to the exports object. So, there are two references to the initial exports object: the exports parameter and the module.exports property.

The value returned from require is the module.exports property.

In our code, we overwrote the module.exports property with the hsl function, which is why we can call the result of require immediately (for example, require('./')(180, 100, 50)).

The following diagram serves to visualize the module loading process at a high level:

How Node loads modules