SkillAgentSearch skills...

Utils

A toolkit of utilities used across all the AdonisJS, Edge, and Japa packages

Install / Use

/learn @poppinss/Utils
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

@poppinss/utils

A toolkit of utilities used across all the AdonisJS, Edge, and Japa packages

[![gh-workflow-image]][gh-workflow-url] [![typescript-image]][typescript-url] [![npm-image]][npm-url] [![license-image]][license-url]

Why does this package exist?

My open-source projects (including AdonisJS) use many single-purpose utility packages from npm. Over the years, I have faced the following challenges when using these packages.

  • Finding the perfect package for the use case takes a lot of time. The package should be well maintained, have good test coverage, and not accumulate debt by supporting some old versions of Node.js.
  • Some packages are great, but they end up pulling a lot of unnecessary dependencies like (requiring TypeScript as a prod dependency)
  • Sometimes, I use different packages for the same utility (because I cannot remember what I used last time in that other package). So I want to spend time once choosing the one I need and then bundle it inside @poppinss/utils.
  • Some authors introduce breaking changes too often (not a criticism). Therefore, I prefer wrapping their packages with my external API only to absorb breaking changes in one place.
  • The rest are some handwritten utilities that fit my needs.

Re-exported packages

The following packages are re-exported as it is and you must consult their documentation for usage instructions.

| Package | Subpath export | | ------------------------------------------------------------------------ | --------------------------- | | @poppinss/exception | @poppinss/utils/exception | | @poppinss/string | @poppinss/utils/string | | @poppinss/types | @poppinss/utils/types |

Other packages to use

A note to self and others to consider the following packages.

| Package | Description | | ------------------------------------------------------------------ | ------------------------------------------------------------------------------ | | he | For escaping HTML entities and encoding Unicode symbols. Has zero dependencies | | @sindresorhus/is | For advanced type checking. Has zero dependencies | | moize | For memoizing functions with complex parameters |

Package size

Even though I do not care much about package size (most of my work is consumed on the server side), I am mindful of the utilities and ensure that I do not end up using really big packages for smaller use cases.

Here's the last checked install size of this package.

<a href="https://pkg-size.dev/@poppinss/utils@next"><img src="https://pkg-size.dev/badge/install/370120" title="Install size for @poppinss/utils"></a>

Installation

Install the package from the npm registry as follows:

npm i @poppinss/utils

# Yarn lovers
yarn add @poppinss/utils

JSON helpers

Safely parse and stringify JSON values. These helpers are thin wrappers over secure-json-parse and safe-stable-stringify packages.

safeParse

The native implementation of JSON.parse opens up the possibility for prototype poisoning. The safeParse method protects you from that by removing the __proto__ and the constructor.prototype properties from the JSON string at the time of parsing it.

import { safeParse } from '@poppinss/utils/json'

safeParse('{ "a": 5, "b": 6, "__proto__": { "x": 7 } }')
// { a: 5, b: 6 }

safeStringify

The native implementation of JSON.stringify cannot handle circular references or language-specific data types like BigInt. The safeStringify method removes circular references and converts BigInts to strings. The safeStringify method accepts the same set of parameters as the JSON.stringify method.

import { safeStringify } from '@poppinss/utils/json'

const value = {
  b: 2,
  c: BigInt(10),
}

// Circular reference
value.a = value

safeStringify(value)
// '{"b":2,"c":"10"}'

Lodash helpers

Lodash is quite a big library, and we do not use all its helper methods. Therefore, we create a custom build using the lodash CLI and bundle only the needed ones.

Why not use something else: All other helpers I have used are not as accurate or well implemented as lodash.

  • pick
  • pickBy
  • omit
  • omitBy
  • has
  • get
  • set
  • unset
  • mergeWith
  • merge
  • size
  • clone
  • cloneWith
  • cloneDeep
  • cloneDeepWith
  • toPath

You can use the methods as follows.

import lodash from '@poppinss/utils/lodash'

lodash.pick(collection, keys)

FS helpers

fsReadAll

Get a recursive list of all files from a given directory. This method is similar to the Node.js readdir method, with the following differences.

  • Dot files and directories are ignored.
  • Only files are returned (not directories).
  • You can define how the output paths should be returned. The supported types are relative, absolute, unixRelative, unixAbsolute, and url.
import { fsReadAll } from '@poppinss/utils/fs'

const basePath = new URL('./config', import.meta.url)
const files = await fsReadAll(basePath, { pathType: 'url' })

console.log(files)

OPTIONS

<dl> <dt>ignoreMissingRoot</dt> <dd>By default, an exception is raised when the root directory is missing. Setting <code>ignoreMissingRoot</code> to true will not result in an error, and an empty array will be returned.</dd> <dt>filter</dt> <dd>Define a filter to ignore certain paths. The method is called on the final list of files.</dd> <dt>sort</dt> <dd>Define a custom method to sort file paths. By default, the files are sorted using natural sort.</dd> <dt>pathType</dt> <dd>Define how to return the collected paths. By default, OS-specific relative paths are returned. If you want to import the collected files, you must set the <code>pathType = 'url'</code></dd> </dl>

fsImportAll

The fsImportAll method recursively imports all the JavaScript, TypeScript, and JSON files from a given directory and returns their exported values as an object of key-value pairs.

  • If there are nested directories, then the output will also contain nested objects.
  • Value is the exported values from the module. Only the default value is used if a module exports both the default and named values.
import { fsImportAll } from '@poppinss/utils/fs'

const configDir = new URL('./config', import.meta.url)
const collection = await fsImportAll(configDir)

console.log(collection)
// title: Directory structure
├── js
│   └── config.cjs
├── json
│   └── main.json
└── ts
    ├── app.ts
    └── server.ts
// title: Output
{
  ts: {
    app: {},
    server: {},
  },
  js: {
    config: {},
  },
  json: {
    main: {},
  },
}

OPTIONS

<dl> <dt>ignoreMissingRoot</dt> <dd>By default, an exception is raised when the root directory is missing. Setting <code>ignoreMissingRoot</code> to true will not result in an error, and an empty object will be returned.</dd> <dt>filter</dt> <dd>Define a filter to ignore certain paths. By default only files ending with <code>.js</code>, <code>.ts</code>, <code>.json</code>, <code>.cjs</code>, and <code>.mjs</code> are imported.</dd> <dt>sort</dt> <dd>Define a custom method to sort file paths. By default, the files are sorted using natural sort.</dd> <dt>transformKeys</dt> <dd>Define a callback method to transform the keys for the final object. The method receives an array of nested keys and must return an array back.</dd> </dl>

Assertion helpers

The following assertion methods offer a type-safe approach for writing conditionals and throwing errors when the variable has unexpected values.

assertExists

Throws AssertionError when the value is false, null, or undefined.

import { assertExists } from '@poppinss/utils/assert'

const value = false as string | false
assertExists(value)

// value is a string

assertNotNull

Throws AssertionError when the value is null.

import { assertNotNull } from '@poppinss/utils/assert'

const value = null as string | null
assertNotNull(value)

// value is a string

assertIsDefined

Throws AssertionError when the value is undefined.

import { assertIsDefined } from '@poppinss/utils/assert'

const value = undefined as string | undefined
assertIsDefined(value)

// value is a string

assertUnreachable

Throws AssertionError when the method is invoked. In other words, this method always throws an exception.

import { assertUnreachable } from '@poppinss/utils/assert'
assertUnreachable()

Base64 encoding

encode

Base64 encodes a string or a Buffer value.

import base64 from '@poppinss/utils/base64'

base64.encode('hello world')
// aGVsbG8gd29ybGQ=

urlEncode

The urlEncode method returns a base64 string safe for use inside a URL. The following characters are replaced.

  • The + character is replaced with -.
  • The / character is replaced with _.
  • Trailing =
View on GitHub
GitHub Stars77
CategoryDevelopment
Updated3d ago
Forks15

Languages

TypeScript

Security Score

100/100

Audited on Mar 28, 2026

No findings