Package Exports
- @poppinss/utils
- @poppinss/utils/build
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (@poppinss/utils) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
Utils
Collection of reusable scripts used by AdonisJS core team
This module exports a collection of re-usable utilties to avoid re-writing the same code in every other package. We also include a handful of Lodash utilities, which are used across the AdonisJS packages eco-system.
Table of contents
- Installation
- Exception
- fsReadAll
- requireAll
- esmRequire
- esmResolver
- resolveFrom
- Lodash utilities
- Base 64 Encode/Decode
- Random String
- Safe equal
- Message Builder
- Audit report
Installation
Install the package from npm registry as follows:
npm i @poppinss/utils
# yarn
yarn add @poppinss/utilsand then use it as follows:
import { requireAll } from '@poppinss/utils'
requireAll(__dirname)Exception
A custom exception class that extends the Error class to add support for defining status and error codes.
import { Exception } from '@poppinss/utils'
throw new Error('Something went wrong', 500, 'E_RUNTIME_EXCEPTION')
throw new Error('Route not found', 404, 'E_ROUTE_NOT_FOUND')fsReadAll
A utility to recursively read all script files for a given directory. This method is equivalent to
readdir + recursive + filter (.js, .json, .ts).
import { fsReadAll } from '@poppinss/utils'
const files = fsReadAll(__dirname) // array of stringsYou can also define your custom filter function. The filter function must return true for files to be included.
const files = fsReadAll(__dirname, (file) => {
return file.endsWith('.foo.js')
})requireAll
Same as fsReadAll, but instead require the files. Helpful when you want to load all the config files inside a directory on app boot.
import { requireAll } from '@poppinss/utils'
const config = requireAll(join(__dirname, 'config'))
{
file1: {}, // exported object
file2: {} // exported object
}esmRequire
Utility to require script files wihtout worrying about CommonJs and ESM exports. This is how it works.
- Returns the exported value for
module.exports. - Returns the default value is an ESM module has
export default. - Returns all exports if is an ESM module and doesn't have
export default.
foo.js
module.exports = {
greeting: 'Hello world'
}foo.default.js
export default {
greeting: 'Hello world'
}foo.esm.js
export const greeting = {
greeting: 'hello world'
}import { esmRequire } from '@poppinss/utils'
esmRequire('./foo.js') // { greeting: 'hello world' }
esmRequire('./foo.default.js') // { greeting: 'hello world' }
esmRequire('./foo.esm.js') // { greeting: { greeting: 'hello world' } }esmResolver
The esmResolver method works similar to esmRequire. However, instead of requiring the file, it accepts the object and returns the exported as per the same logic defined above.
import { esmRequire } from '@poppinss/utils'
esmResolver({ greeting: 'hello world' }) // { greeting: 'hello world' }
esmResolver({
default: { greeting: 'hello world' },
__esModule: true,
}) // { greeting: 'hello world' }
esmResolver({
greeting: { greeting: 'hello world' },
__esModule: true,
}) // { greeting: { greeting: 'hello world' } }resolveFrom
Works similar to require.resolve, however it handles the absolute paths properly.
import { resolveFrom } from '@poppinss/utils'
resolveFrom(__dirname, 'npm-package') // returns path to package "main" file
resolveFrom(__dirname, './foo.js') // returns path to `foo.js` (if exists)
resolveFrom(__dirname, join(__dirname, './foo.js')) // returns path to `foo.js` (if exists)Lodash utilities
Lodash itself is a bulky library and most of the times, we don't need all the functions from it. For this purpose, the lodash team decided to publish individual methods to npm as packages. However, most of those individual packages are outdated.
At this point, whether we should use the complete lodash build or use outdated individual packages. Both are not acceptable.
Instead, we make use of lodash-cli to create a custom build of all the utilities we ever need inside the AdonisJS eco-system and export it as part of this package. Why part of this package?
Well, creating custom builds in multiple packages will cause friction, so it's better to keep it at a single place.
Do note: There are no Typescript types for the lodash methods, since their CLI doesn't generate one and the one published on
@types/lodashpackage are again maintained by community and not the lodash core team, so at times, they can also be outdated.
import { lodash } from '@poppinss/utils'
lodash.snakeCase('HelloWorld') // hello_worldExported methods
Following is the list of exported helpers.
Base 64 Encode/Decode
Following helpers for base64 encoding/decoding also exists.
encode
import { base64 } from '@poppinss/utils'
base64.encode('hello world')
base64.encode(Buffer.from('hello world', 'binary'))decode
import { base64 } from '@poppinss/utils'
base64.decode(base64.encode('hello world'))
base64.decode(base64.encode(Buffer.from('hello world', 'binary')), 'binary')urlEncode
Same as encode, but safe for URLS and Filenames
urlDecode
Same as decode, but decodes the urlEncode output values
Random String
A helper to generate random strings of a given length. Uses crypto under the hood.
import { randomString } from '@poppinss/utils'
randomString(32)
randomString(128)Safe equal
Compares two values by avoid timing attack. Accepts any input that can be passed to Buffer.from
import { safeValue } from '@poppinss/utils'
if (safeValue('foo', 'foo')) {
}Message Builder
Message builder provides a sane API for stringifying objects similar to JSON.stringify but has a few advantages.
- It is safe from JSON poisoning vulnerability.
- You can define expiry and purpose for the encoding. The
verifymethod will respect these values.
The message builder alone may seem useless, since anyone can decode the object and change its expiry or purpose. However, you can generate an hash of the stringified object and verify for tampering by validating the hash. This is what AdonisJS does for cookies.
import { MessageBuilder } from '@poppinss/utils'
const builder = new MessageBuilder()
const encoded = builder.build(
{ username: 'virk' },
'1 hour',
'login',
)Now verify it
builder.verify(encoded) // returns null, no purpose defined
builder.verify(encoded, 'register') // returns null, purpose mismatch.
builder.verify(encoded, 'login') // return { username: 'virk' }Audit report
Click here to see the latest npm audit report.