install.fairie/.config/docs/contributing/tools.md
2022-12-24 21:35:29 -05:00

4.8 KiB

Preferred Libraries

A lot of research has gone into determining what the best tool is for each common task that gets performed. These tasks can range from generating a CLI help menu to validating user inputs. You can browse through the dependencies in the package.json file of our NPM package starting template to get a better idea of what we prefer.

Logger

If you browsed through the package.json file mentioned above, you will see that we are including pino and pino-pretty as dependencies. Both should be used to handle all logging. There should be no console.log commands in the project. Instead, all of the logging should be handled by a Logger class. You can see an example provided by the Buildr project here. When creating a Logger class, feel free to copy and paste from the linked Buildr Logger class file.

CLI / Help Menu

Commander.js is the leading solution for handling CLI commands and generating terminal help menus. The library is included in the aforementioned starting template and should be used in any project that includes CLI command capabilities or CLI help menus. Using this library is not a hard requirement but any deviations from it should be approved by the project's maintainer.

Interactive CLI Prompts

Inquirer.js is our preferred library for providing enhanced CLI prompts. You might choose to use this library if part of the app includes prompting the user for different values. Browsing through the capabilities of Inquirer.js using the link provided is highly encouraged. If you are not utilizing this dependency then it should be removed from the package.json. The same goes for any package that is unused - if it is not being used then throw it out!

Data Model Validation

One feature we like to include in all of our projects that rely on any input parameters is data validation. For instance, if one of the parameters that is passed in is supposed to be a FQDN and the user passes in a string that does not match the RegEx of a FQDN, then the user should be notified with a simple, well-formatted error message (which is generated by pino). We accomplish this by leveraging the class-validator library. There are tons of examples provided on their page and we highly encourage you to get comfortable using the library by checking out the link.

In order to utilize class-validator, you have to assign all input data to a model. The model is then set up to use class-validator decorators on each attribute. With the data model populated, you can use the class-validator library to validate the input. Take the following as an example:

import { validate, IsInt, IsFQDN, Min, Max } from 'class-validator';

export class Post {
  @IsInt() // This is a decorator
  @Min(0)
  @Max(10)
  rating: number;

  @IsFQDN()
  site: string;
}

let post = new Post();
post.rating = 11;          // Should not pass validation
post.site = 'googlecom';   // Should not pass validation

validate(post).then(errors => {
  // errors is an array of validation errors
  if (errors.length > 0) {
    console.log('validation failed. errors: ', errors);
  } else {
    console.log('validation succeed');
  }
});

Using the library above can provide real value to our users. By validating the data before running any business logic, we can save the user time by taking out the guess work required for debugging. Please note that in practice, the Post model/class would be seperated into a file stored in src/models/post.model.ts.

All data inputs should utilize this form of validation. If the class-validator project does not provide a decorator that can properly validate the input data then you can extend the library by creating a custom validation decorator. There is an example of how to create a custom validator in the Buildr project.

Update Notifier

As a feature meant to make our packages stand out from the crowd, we prefer that you incorporate update-notifier in the project to notify users of any updates to the NPM package.

Environment Variables

In some cases, a package might rely on sensitive data that should not be included in git repositories. In this case, you may choose to utilize environment variables. If that is the case, then please include support for dotenv which allows users to load environment variables by defining a .env file. The users can then add .env to their .gitignore file to keep the .env file out of their project's repository.