I Deleted My NPM Packages

I deleted all 4 of my NPM packages today. It has been over a year since I’ve last updated them, and I didn’t want to add any more clutter to the system.

I’ve always thought that having published open source code meant something, but then I realized that it doesn’t matter if it’s not useful.

Learning how to package libraries and applications was a good experience, though, and I would probably publish stuff IF/WHEN I have actually solved a need. Here are the reasons why I deleted each of them.

TimeInterval nominal type: libtime

This should just be a single file that can be easily copied and extended. I also created a GitHub Gist so it can also be downloaded.

/* TimeInterval nominal type and converters */
declare const TypeSymbol: unique symbol;
export type TimeInterval = number & { [TypeSymbol]: 'TimeInterval' };

/* Functions for converting to TimeInterval */
export const milliseconds = (howMany: number) => howMany as TimeInterval;
export const seconds = (howMany: number) => (howMany * 1000) as TimeInterval;
export const minutes = (howMany: number) => (howMany * 1000 * 60) as TimeInterval;
export const hours = (howMany: number) => (howMany * 1000 * 3600) as TimeInterval;
export const days = (howMany: number) => (howMany * 1000 * 3600 * 24) as TimeInterval;
export const weeks = (howMany: number) => (howMany * 1000 * 3600 * 24 * 7) as TimeInterval;

/* Functions for converting to numbers */
export const toSeconds = (timeInterval: TimeInterval) => timeInterval / 1000;
export const toMilliseconds = (timeInterval: TimeInterval) => timeInterval as number;

This can be used like so:

async function delay(duration: TimeInterval): Promise<void> {
  return new Promise<void>((resolve) => {
    setTimeout(resolve, toMilliseconds(duration))
  })
}

async function main() {
  // do something here...

  await delay(minutes(3))

  // do another thing here...
}

NestJS File Logger Module: nestjs-file-logger

This is also better suited to be just a copy-pasta, since I wouldn’t have been able to offer a decent amount of customizability, nor did I want to. I just wanted to publish a package for the sake of it.

import "reflect-metadata";
import { Module, ConsoleLogger, Inject, Injectable } from "@nestjs/common";
import { Logger as WinstonLogger, format, transports } from "winston";
import { WinstonModule } from "nest-winston";

type Level = "debug" | "log" | "warn" | "error";
@Injectable()
export class FileLogger extends ConsoleLogger {
  @Inject("winston") logger: WinstonLogger;
  private doLog(level: Level, message: any, ...optionalParams: any[]) {
    super[level](message, ...optionalParams);
    this.logger[level === "log" ? "info" : level](
      JSON.stringify([message instanceof Error ? message.stack : message, ...optionalParams])
    );
  }
  public debug(message: any, ...optionalParams: any[]): void { this.doLog("debug", message, ...optionalParams); }
  public log(message: any, ...optionalParams: any[]): void { this.doLog("log", message, ...optionalParams); }
  public warn(message: any, ...optionalParams: any[]): void { this.doLog("warn", message, ...optionalParams); }
  public error(message: any, ...optionalParams: any[]): void { this.doLog("error", message, ...optionalParams); }
}

const { combine, timestamp, printf } = format;
const logFormat = printf(({ level, message, timestamp }) => `[${timestamp}] ${level}: ${message}`);

const CustomWinstonModule = WinstonModule.forRoot({
  format: combine(timestamp({ format: () => new Date().toISOString() }), logFormat),
  transports: [
    new transports.File({ filename: "logs/error.log", level: "warn" }),
    new transports.File({ filename: "logs/combined.log", level: "info" }),
    new transports.File({ filename: "logs/debug.log", level: "debug" }),
  ],
});

@Module({ imports: [CustomWinstonModule], providers: [FileLogger], exports: [FileLogger] })
export class LoggerModule { }

Stolen from the README:

/* Import `LoggerModule` into your `AppModule` */
import { Module } from "@nestjs/common";
import LoggerModule from "nest-file-logger";

@Module({
  imports: [LoggerModule],
})
export class AppModule {}

/***************************************/

/* Use `FileLogger` on application setup: */
import { NestFactory } from "@nestjs/core";
import { FileLogger } from "nest-file-logger";
import { AppModule } from "./app.module";

const app = await NestFactory.create(AppModule);
app.useLogger(app.get(FileLogger));

Link to Gist

Create Blog File CLI: create-md-blog

This was a CLI application that prompts you for a title and tags (even before you write the actual blog post) and creates a Markdown file containing this metadata. That’s it. And I published it.

This did not need to exist at all. It’s basically just a hammer looking for a nail. Or me, an NPM-obsessed dev, looking for something to publish. It probably took 100x more time to create this than the amount of time I’ve saved using this CLI application. These days I just use hugo new post/<title>.md.

NestJS Dependency Graph: nestjs-dependency-graph

This one would’ve actually been useful if it wasn’t so hard to set up. Fortunately, nestjs-spelunker is a similar tool that is actually maintained and comes with a more portable JSON format.

Charles Ancheta

Computer Engineer


These should've just been Github gists

By Charles Ancheta, 2023-05-10

tags: js npm trash-packages