npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@brmorillo/utils

v14.1.1

Published

Production-ready utility library for JS/TS — 27 modules behind one type-safe API: arrays, objects, strings, crypto, JWT, UUID, sorting, queues, caches, HTTP, logging, storage and more.

Readme

@brmorillo/utils

npm version CI Downloads Bundle size Node.js TypeScript License: LGPL-3.0

If you have a problem, it's probably already solved here.

A comprehensive, production-ready utility library for JavaScript/TypeScript. It bundles ~27 modules — array/object/string/number helpers, cryptography, hashing, JWT, ID generators, data structures, HTTP, logging, storage and more — behind one type-safe, consistent API.

  • 🎯 Type-safe — full TypeScript types, ships its own declarations
  • 📦 Dual build — CommonJS and ESM, tree-shakeable
  • 🧩 Consistent API — every utility takes a single destructured object argument
  • 🚨 Typed errors — branchable error hierarchy with machine-readable codes
  • 🔒 Secure defaults — authenticated crypto, JWT algorithm allowlist, path-traversal protection
  • 🧪 Well tested — large unit/integration suite with high coverage

Installation

bun add @brmorillo/utils
# or
npm install @brmorillo/utils
# or
pnpm add @brmorillo/utils
# or
yarn add @brmorillo/utils

Requires Node.js >= 18.

Quick start

import { ArrayUtils, StringUtils, HashUtils } from '@brmorillo/utils';

// Arrays
ArrayUtils.removeDuplicates({ array: [1, 2, 2, 3] }); // [1, 2, 3]

// Strings
StringUtils.toCamelCase({ input: 'hello world' }); // "helloWorld"

// Hashing
HashUtils.sha256Hash({ value: 'sensitive data' }); // "ef92b778..."

Import only what you need — the package is tree-shakeable, so unused modules are dropped by your bundler.

Conventions

These rules hold across the whole library:

  • One object argument. Static utility methods take a single destructured object: NumberUtils.clamp({ value, min, max }), SortUtils.quickSort({ array }), CryptUtils.aesEncrypt({ data, secretKey }). The configurable services (HttpService, LogService, StorageService) use a method-style API instead.
  • Typed errors. Failures throw a typed error, never a bare Error: ValidationError (bad input), StorageError, HttpError, QueueFullError, or BaseError with a code. See error handling.
  • Predicate naming. Property predicates are is* (isEven, isPrime, isPalindrome); format validators are isValid* (isValidEmail, isValidCPF).

Modules

Full per-module reference lives in docs/. Each module has a complete page under docs/<module>/README.md.

Core data

| Module | Class | Highlights | | --- | --- | --- | | array | ArrayUtils | removeDuplicates, intersect, flatten, groupBy, shuffle, sort | | object | ObjectUtils | deepClone, deepMerge, pick, omit, flattenObject, diff, deepFreeze | | string | StringUtils | toCamelCase, toKebabCase, truncate, isPalindrome, replacePlaceholders | | number | NumberUtils | roundToDecimals, isEven, clamp, factorial, toCents, random ranges | | math | MathUtils | percentage, gcd, lcm, clamp, isPrime, randomInRange |

Data & validation

| Module | Class | Highlights | | --- | --- | --- | | convert | ConvertUtils | space, weight, volume, value (type/roman) | | date | DateUtils | intervals, add/remove time, diff, time zones (Luxon) | | validation | ValidationUtils | isValidEmail, isValidURL, isValidJSON, CPF/CNPJ/RG |

Security & cryptography

| Module | Class | Highlights | | --- | --- | --- | | crypt | CryptUtils | AES-256-GCM, ChaCha20-Poly1305, RSA (OAEP), ECC | | hash | HashUtils | bcrypt, SHA-256/512, random tokens | | jwt | JWTUtils | generate, verify (algorithm allowlist), decode, refresh |

Identifiers

| Module | Class | Highlights | | --- | --- | --- | | uuid | UUIDUtils | UUID v1/v4/v5 + validation | | cuid | CuidUtils | CUID2 generation + format check | | snowflake | SnowflakeUtils | Snowflake IDs with custom epoch |

Data structures & algorithms

| Module | Class | Highlights | | --- | --- | --- | | sort | SortUtils | 18 sorting algorithms | | queue | QueueUtils | queue, stack, priority/delay queue, circular & multi-queue | | cache | CacheUtils, Cache | LRU/LFU/FIFO caches with TTL | | benchmark | BenchmarkUtils | timing & memory benchmarks |

System & I/O

| Module | Class | Highlights | | --- | --- | --- | | file | FileUtils | read/write/copy/move/hash files | | request | RequestUtils | extract IP / user-agent metadata | | http | HttpService | configurable HTTP client (Axios or native) | | log | LogService | structured logging (Pino/Winston/Console) | | storage | StorageService | local filesystem or AWS S3 |

Events & control flow

| Module | Class | Highlights | | --- | --- | --- | | event | EventUtils | type-safe event emitter | | retry | RetryUtils | retry with capped backoff + jitter | | lazy-loader | LazyLoader | lazy, cached value creation |

Shared

| Module | Highlights | | --- | --- | | errors | BaseError, ValidationError, HttpError, StorageError, QueueFullError |

Configurable services

HttpService, LogService and StorageService are configurable singletons. You can use them directly or via the Utils facade:

import { Utils } from '@brmorillo/utils';

const utils = Utils.getInstance({
  logger: { type: 'pino', level: 'info', prettyPrint: true },
  http: { clientType: 'axios', baseUrl: 'https://api.example.com', timeout: 5000 },
  storage: { providerType: 'local', local: { basePath: './storage' } },
});

utils.getLogger().info('Application started');
const res = await utils.getHttpService().get('/health');
await utils.getStorageService().uploadFile('notes.txt', 'hello');

See http, log and storage for full configuration options.

Error handling

Every failure is a typed error extending BaseError, so you can branch on the type or the code:

import { ValidationError, BaseError } from '@brmorillo/utils';

try {
  CryptUtils.aesEncrypt({ data: 'x', secretKey: 'too-short' });
} catch (error) {
  if (error instanceof ValidationError) {
    console.error('Bad input:', error.message, error.field);
  } else if (error instanceof BaseError) {
    console.error(error.code, error.details); // e.g. 'CRYPTO_ERROR'
  }
}

Wrapped errors keep the original under the standard cause property. BaseError.toJSON() omits the stack trace by default (safe to return in HTTP responses). See errors.

Security

  • Authenticated encryption — AES-256-GCM and ChaCha20-Poly1305 return an authTag that is verified on decryption; tampering throws. RSA uses OAEP. RC4 is not provided.
  • JWTverify enforces an algorithm allowlist (defaults to HS256, rejects none); generate sets a default expiry and pins the algorithm.
  • Storage — the local provider confines all paths to its configured root.
  • Object utilitiesdeepMerge/unflattenObject reject prototype-pollution keys.

To report a vulnerability or read the full list of supported versions and security guarantees, see the Security Policy.

Documentation

Development

bun install          # install dependencies (this project uses bun)
bun run build        # typecheck + build (CJS + ESM + .d.ts)
bun run test         # run unit + integration tests
bun run lint         # lint
bun run format       # format with Prettier

Contributing

All contributions must follow these conventions:

  • Commit messagesConventional Commits: feat:, fix:, docs:, refactor:, test:, chore:, perf:.
    Breaking changes get a ! suffix (feat!:, refactor!:) and a BREAKING CHANGE: footer.
  • Branch namingfeature/<short-name>, fix/<issue>, docs/<topic>, chore/<task>.
  • PR process — open a PR against main; the CI pipeline (type-check → lint → test with coverage gate → build → secret scan) must pass. The pr-version workflow automatically commits the version bump (chore(release): vX.Y.Z) to your branch before merge.
  • v13 API contract — this is a stable, API-frozen line. Only additive, non-breaking changes are accepted: new methods, new optional parameters, new exports. Signature changes, removals, or observable behavior changes require a new major version.
  • Mutability convention — data-transforming methods must be non-mutating by default. Opt-in mutation is exposed via inPlace?: boolean (default false). Both invariant test suites (immutability.spec.ts and inplace-invariant.spec.ts) must stay green.
  • Typed errors only — never throw new Error(...). Use the typed errors from src/errors.
  • TSDoc on every public member — all public methods, constructors, and exported helpers must have a /** */ block with at least a summary line.
  • English only — all identifiers, comments, doc strings, and test descriptions must be in English.

Dependency update policy

All runtime and development dependencies are pinned to exact versions (no ^, ~, or latest) in package.json. This ensures fully reproducible installs and makes every dependency change an intentional, reviewable commit.

Update schedule

Dependency updates are performed once a month, on the first working day of each month.

Version lag — 3-month rule

We intentionally stay at least 3 months behind the latest published version of every dependency. This buffer gives the community time to discover and disclose supply-chain attacks, malicious publishes, and critical regressions before we adopt them.

Example: if axios publishes 2.0.0 on 1 March 2025, the earliest we adopt it is 1 June 2025.

How to update a dependency

  1. Check whether the target version is at least 3 months old:
    npm view <package> time --json   # lists publish timestamps for every version
  2. Read the changelog and check for breaking changes, CVEs, or supply-chain advisories.
  3. Manually edit the version string in package.json (no ^ or ~).
  4. Run bun install to refresh bun.lock.
  5. Run the full test suite and build:
    bun run build
    CI=true bun run test:ci
  6. Commit with:
    chore(deps): update <package> from X.Y.Z to A.B.C
  7. Open a PR. The CI pipeline validates the updated lockfile automatically.

CJS-compatibility check

Before bumping any runtime dependency to a new major, verify it still ships a CommonJS build:

node -e "require('<package>')"                        # must not throw
node -p "Object.keys(require('<package>/package.json').exports)"   # must include 'require'

The following packages are permanently pinned to a specific major for CJS compatibility:

| Package | Pinned major | Reason | | --- | --- | --- | | uuid | 11.x | v14+ is ESM-only | | @paralleldrive/cuid2 | 2.x | v3+ is ESM-only |

License

LGPL-3.0-only © Bruno Morillo

This library is free to use in any project (including commercial ones). You may not distribute it as a closed-source product or sell it as your own. Any modifications to the library itself must be released under the same license.