JSPM

  • Created
  • Published
  • Downloads 10
  • Score
    100M100P100Q57807F
  • License MIT

pcall.js is an extendable utility that let you encapsulates asynchronous operations safely ━━ Zero-dependency, Zero-configuration, Lightweight

Package Exports

  • pcall.js

Readme

PCALL.js

🔥 Protected calls for JS with Superpowers 🦄

🚧 DEVELOPMENT ⛔
logo-of-pcall

Centralized your Error handling, Monitoring, Notifications and more

  

🌈 no more nested try...catch!

pcall.js is an extendable utility that let you encapsulates asynchronous operations safely

Zero dependency, Zero configuration, Lightweight, Framework agnostic


Features

  • Zero-dependency: Works in Node.js (ESM & CJS) and all modern browsers
  • Zero-configuration: Provides opt-in configuration for advance usage
  • Fault-tolerant: Uniform and deterministic asynchronous operations
  • Extendable: Lifecycle Hooks, Processors, Serializer, Parser
  • Humanized API: Simple to get started with a reasonable API
  • Lightweight: under (2 KB)

Prelude

You might have an entire function wrapped in a try..catch; In which you have to figure out which call throw the error, Lack of control and visibility.

You might wrap each async call in it's own try...catch; Which is ugly and too verbose.

You might write a utility to wrap an capture each call.

It's fragmented, hacky and not consistent.


Inspiration

Lua approach to error handling is simple yet powerful. ^Lua:8.4, ^Lua:8.5

🔹 Pcall.js is heavily inspired by Lua pcall with superpowers!


SYNOPSIS

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

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 status code (a boolean), which is true if the call succeeds without errors. And all results from the call, on second element; [true, {res}]

In case of any error, pcall returns false plus the error message; [false, {err}]


Installation

# install
npm install pcall.js

Usage

// ESM
import pcall from 'pcall.js'

// CJS
const pcall = require('pcall.js')

Basic Usage

// some promise
const myPromise = (...x) =>
  new Promise((resolve, reject) =>
    Math.random() > 0.5 ? resolve(x) : reject(x),
  );
import pcall from 'pcall.js'

const [ok, res] = await pcall(myPromise, 'hoge', [99, 7], { xorg: 'X11' });

console.log(ok, res)
// <true|false>,  <...>

Advance Usage*

🚧 NOT_IMPLEMENTED

import Pcall from 'pcall.js'

// Create a custom pcall instance for advance usage
const pcall = Pcall.setup({
  // runs on success, passing context and result
  pass_hook: (ctx, res) => { /* do stuff */ },

  // runs on failure, passing context and error
  fail_hook: (ctx, err) => { /* do stuff */ },

  // runs before success hook, transform the success result
  pass_transformer: (res) => ({ hoge: 'fuga', ...res }),

  // runs before failure hook, transform the failure error
  fail_transformer: (err) => ({ frob: 'xyzzy', err.message })

  // NOTE: the transformers only modify the success/failure message
  // NOT the structure
})

const [ok, res] = await pcall(myPromise, 'hoge', ['fuga', 'nyoro'], { xorg: 'X11' });

console.log(ok, res)
// <true|false>,  <...>

Development

# run test playground in watch mode
npm run dev

# build production
npm run build

# build stub
npm run build:stub

TODO

  • 🔸Lifecycle Hooks
  • 🔸Transformers for Success/Failure
  • 🔸Serializer
  • 🔸Parser
  • 🔸JSDoc
  • 🔸ESLint
  • 🔸Docs
  • 🔸Tests
  • 🔸Examples

License

MIT