Back to all post

Published at: 5/21/2024, 12:00:00 AM

How to update a deprecated npm package?

Alright, let me put us in situation. We got our latest report from Olynpm about the olynpm-cli project.

Some regular maintenance is needed as our dependencies are not up to date. A few minor updates here and a patch version there.

Unfortunately, that isn’t all. One of the packages in the project is also deprecated.

The minor and patch versions are usually easy to solve. Applying the suggestions from the package report card will solve the problem.

Once applied the update, I’ll re-test and if all good a new version of the package will be published.

I’ll then trigger the creation of another Olynpm report and share progress with the team. However, the deprecated package is still there, and needs fixing.

1) Find a Replacement for the deprecated package.

Once decided to work on the issue, the options are finding another suitable package, building something on your on or removing it completely.

As we still want logging in our project, we will be looking at finding another suitable package as first option before considering implementing something on our own.

So, how do I find a new replacement for the package? A simple heuristic, find the packages that is the closest based on matching features and then apply the organization practices supply chain security . I’ll be using the project OSS Scorecard as to simplify the criteria for this article.

As that we’re replacing ‘npmlog’, my starting point will be looking at the available resources in Olynpm to understand what are the features of the package. The package report card provides the links to the npm page, its github page and the website if any (not in this case).

We can summarize the `npmlog` package key functionality as:

  • Basic logging utility, simple to use: I.e:

    log.info('fyi', 'I have a kitty cat: %j', myKittyCat)

  • Customizable logging levels and colored output.

  • Logs are written to `stderr` by default but can be redirected or handled via event listeners.

  • It emits events for each log message, facilitating further custom handling

So, we need something similar. Fortunately, it’s easy to search for resources all around the web comparing different loggers for nodejs projects. Here is an article comparing alternatives. From that list is clear that the contenders for replacing are Pino and Winston. They are the most popular, feature rich and most maintained.

Also their OSS Score cards score well on the high risks checks: Actively maintained, code review in place, no vulnerabilities, no binaries artifacts. In this case, Pino scores better than Winston in other checks like Available Security policy.

Considering also our use case, where the footprint of the logging library is small, Pino seems to be a right fit.

2) Replacing the deprecated package.

First, I’ll install the selected packaged in the project:

bash
> pnpm add pino

As next step, I’ll look at the places in the code where ‘npmlog’ is being used and replace the log calls with the ones from Pino. In this case it’s super easy:

javascript
/**
* @file: https://github.com/fresnosatech/olynpmcli/blob/v0.1.4/src/commands/reportUrl.ts 
*/
 
-import log from "npmlog";
+import pino from "pino";
+
+const log = pino();
 
...

and apply the same change in the other file:

javascript
/**
* @file: https://github.com/fresnosatech/olynpm-cli/blob/v0.1.4/src/commands/createReport.ts 
*/
 
-import log from "npmlog";
+import pino from "pino";
+
+const log = pino();
 
...

Next we build and test the command:

bash
> pnpm build && pnpm olynpm track
 
... 
 
Creating report: olynpm
{"level":30,"time":1716473323228,"pid":97011,"hostname":"local","msg":"olynpm"}
{"level":30,"time":1716473323228,"pid":97011,"hostname":"local","msg":"olynpm"}
{"level":30,"time":1716473323228,"pid":97011,"hostname":"local","msg":"olynpm"}
{"level":30,"time":1716473323229,"pid":97011,"hostname":"local","msg":"olynpm"}
{"level":30,"time":1716473323229,"pid":97011,"hostname":"local","msg":"olynpm"}
 
... 

Alright, the logging works. However, the formatting is not exactly as we were hoping.

It shows a level number instead of the severity we had before (‘info’, ‘warn’, ‘error’, etc) and also the “msg” is always what we had as “LOG_PREFIX”.

Replacing the definition of the const log = …. with the following code give us something closer to what we are expecting:

javascript
/**
* @file: https://github.com/fresnosatech/olynpm-cli/blob/v0.1.4/src/commands/createReport.ts 
*/
 
import pino from "pino";
 
const log = pino({
  level: process.env.PINO_LOG_LEVEL || "info",
  formatters: {
    level: (label) => {
      return { severity: label.toUpperCase() };
    },
  },
});
 
...

And replacing the “LOG_PREFIX” in the log calls for something more meaningful:

javascript
log.error({ log_prefix: LOG_PREFIX }, "package.json file not found.");

Gets you a better output:

bash
> pnpm build && pnpm olynpm track
 
... 
 
Creating report: olynpm
{"severity":"INFO","timestamp":"2024-05-23T17:00:43.586Z","pid":1306,"hostname":"local","flow":"olynpm","msg":"Found: commander@^12.0.0"}
{"severity":"INFO","timestamp":"2024-05-23T17:00:43.586Z","pid":1306,"hostname":"local","flow":"olynpm","msg":"Found: dotenv@^16.4.5"}
{"severity":"INFO","timestamp":"2024-05-23T17:00:43.586Z","pid":1306,"hostname":"local","flow":"olynpm","msg":"Found: npmlog@^7.0.1"}
{"severity":"INFO","timestamp":"2024-05-23T17:00:43.586Z","pid":1306,"hostname":"local","flow":"olynpm","msg":"Found: pino@^9.1.0"}
{"severity":"INFO","timestamp":"2024-05-23T17:00:43.586Z","pid":1306,"hostname":"local","flow":"olynpm","msg":"Found: semver@^7.6.0"}
 
... 

Last but not least we need to remove

bash
> pnpm remove npmlog

Let’s commit the changes and create a new report:

Now it’s all good!