Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

187 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

logo-of-pcall

ƀ𝖒𐀠LL.ᴊꜱ

Result/Monad like tuples for JS

unwrap promises safely with minimum footprint

── β•Άβ•΄β•Άβ•΄β•Άβ•΄β•Άβ•΄β•Άβ•΄β•Άβ•΄β•Άβ•΄ ──

πŸ“¦ Extremely Small

🧬 Lifecycle Hooks

🎯 Concise Signature

πŸ’  Group Side Effects

β›” try/catch HELL πŸ‘Ή

🌟 Better Visibility and Control

🌐 Works in ESM & CJS

✱ Minimal Obsessive Disorder



Inspiration

pcall.js is heavily inspired by

πŸ”Ή Lua pcall status, res

πŸ”Ή Elixir/Erlang Result Monad {:ok/:error, reason/value}

πŸ”Ή Rust Result<T, E>

πŸ”Ή Go []error

with superpowers πŸ¦„!


SYNOPSIS

pcall({f}, {arg1}, {...})

[err, res]

pcall() Calls function {f} with the given arguments in protected mode.

This means that any error inside {f} is not propagated;

Instead, pcall catches the error and returns a tuple.

Its first element is the err object,

Which is null if the call succeeds without errors.

And all results from the call, on second element; [null, {res}]


Usage

# install
npm install pcall.js
// ESM
import Pcall from 'pcall.js'

// CJS
const Pcall = require('pcall.js')
const [err, res] = await Pcall(asyncFn, a, b, c, /* Β·Β·Β· */)
const pcall = new Pcall({
  onSuccess: console.log,
  onFailure: console.error,
  onFinally: console.info,
  timeout: 30_000,
  transformOnSuccess: (res) => res,
  transformOnFailure: (err) => err,
  noTrace: false
})
const [err, res] = await pcall(asyncFn, a, b, c, /* Β·Β·Β· */)
:Fulfill [null, res]
:Reject  [err, null]

Convert

import { readFile } from 'node:fs/promises'

// πŸ”» BEFORE
try {
  const res = await readFile('./package.json', { encoding: 'utf8' })
} catch(error) {
  console.error(error, 'πŸ”₯')
}

// ─────────────────
// πŸ”ΉAFTER
import Pcall from 'pcall.js'
const [err, res] = await Pcall(readFile, './package.json', { encoding: 'utf8' })

// πŸ”ΈTHROW
err && throw new Error("XYZZY", { cause: err });

// ─────────────────
// πŸ”Έ MOCK
// const readJson = new Pcall({
//   fn: readFile,
//   args: [{ encoding: 'utf8' }],
//   transformOnSuccess: (res) => JSON.parse(res),
//   transformOnFailure: (err) => err.message,
// })
// const path = 'test/sample-good.json'
//
// const res = await readJson(path)
// log(res.hogo) // fuga

Options

import { readFile } from 'node:fs/promises'
import Pcall from 'pcall.js'

const pcall = new Pcall({
  onSuccess: console.log,
  onFailure: console.error,
  onFinally: (args, func, span) => { /* πŸ’£ πŸ’£ πŸ’₯ */ },
  transformOnSuccess: (res) => res,
  transformOnFailure: (err) => err,
  timeout: 30_000,
  noTrace: false,
})

const path = './package.json'
const opts = { encoding: 'utf8' }

const [err, res] = await pcall(readFile, path, opts)

πŸ’‘ Check test/ files for more examples


Development

# run test playground in watch mode
npm run dev

# build production
npm run build

# build stub
npm run build:stub

TODO

  • πŸŒ€ Lifecycle Hooks
  • [.] πŸ”Œ Serializer
  • [.] 🧬 Parser
  • [.] πŸ“œ JSDoc
  • [.] πŸ”§ ESLint
  • [o] πŸ“– Docs
  • [o] ⚠️ Tests
  • [o] πŸ’‘ Examples

License

MIT

About

Minimal Result/Monad library inspired by Lua pcall, Elixir Result, and Rust Result with lifecycle hooks and zero dependencies

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Releases

Used by

Contributors

Languages