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 🙏

© 2024 – Pkg Stats / Ryan Hefner

pragmatik

v0.0.413

Published

Parse arguments correctly for variadic functions

Downloads

15

Readme

Pragmatik

This library attempts to solve an age-old problem in JavaScript => how do we correctly parse the arguments inside a function that accepts a variable number of arguments? (See "variadic functions" and "varargs").

This library allows you to elegantly parse arguments at runtime and assign them to the correct/expected variable in the function signature, according to the parsing rules you define. It is most useful for public and private APIs where we want to give our users the convenience of omitting variables, and not requiring them to pass null or other placeholder values. Of course, you should design your APIs well, with simple function calls with limited number of variation in the signature. Using options objects is a great design pattern to keep things simple, but at some point variadic functions become convenient and we must handle them well, without writing buggy code that will fail silently in edge cases.

Disclaimer => the Pragmatik library is in beta

I have seen so many people roll their own solution to this problem - I would be willing to bet at least 1000 JS libraries have public APIs that accept variable number of arguments and/or optional arguments. At best we get bad error messages or no error messages. At worst, we end up with runtimes using the wrong values, until something breaks, or worse until something succeeds. Pragmatik is designed to fail-fast => (1) if your function parsing rules are not valid, an error is thrown (2) if any function cannot be parsed successfully given the runtime arguments and the parsing rules, an error is thrown.

Extensive testing needs to be completed before this library is totally proven. Also need some sanity checks to make sure this is exactly what people need and want. We will incorporate other "types" that can be easily and reliably checked, like 'array'. Unfortunately, type checking beyond simple primitive types is not an effective strategy because you don't know whether the user passed in the argument in the wrong place in the signature or if they passed the wrong value for the right argument.

Basic Usage

The Pragmatik library exports two functions: parse and signature

The following is a function that accepts varargs, and we use Pragmatik to parse the arguments:

const pragmatik = require('pragmatik');

function foo(){
 const [a,b,c,d,e] = pragmatik.parse(arguments, rules);
  
}

so we can call foo above, like so:

foo(true, {zim:'zam'}, function(){});

and Pragmatik can be used to parse the values as they are expected to appear, for example, first we use signature() to define the parsing rules:

const pragmatik = require('pragmatik');

const r = pragmatik.signature({

    mode: 'strict',                        // does not allow two adjacent non-required types to be the same
    allowExtraneousTrailingVars: false,    // no more than 5 arguments allowed
    args: [
      {
        type: 'string',
        required: false,
      },
      {
        type: 'boolean',
        required: true,
      },
      {
        type: 'object',
        required: true,
      },
      {
        type: 'boolean',
        required: false,
      },
      {
        type: 'function',
        required: false,
      }
    ]
 });


function foo(){
 const [a,b,c,d,e] = pragmatik.parse(arguments, rules);
 
 console.log(a,b,c,d,e); 
 // a => undefined
 // b => true
 // c => {zim:'zam'}
 // d => undefined
 // e => function(){}
 
}

if you want better better IDE support, you can do the following instead, but it's fairly unnecessary, (especially considering the purpose of the library is to support varargs):

function foo(a,b,c,d,e){
 var [a,b,c,d,e] = pragmatik.parse(arguments, rules);
  
}

Motivation

As JS is a dynamic language, we can omit arguments completely and still call functions.

For example,

function foo(a,b,c){

}

we can call foo without any arguments at all:

foo();

and this is valid, of course. But in statically typed languages, this probably won't even compile, let alone run :)

So, what if argument a is "optional", but b and c are "required"?

foo might look like:

function foo(a,b,c){
  a = a || 'temp';
  // yadda yadda
  console.log('a:',a,', b:',b,', c:',c);
}

if we call foo like this:

foo('this is b', 'this is c');

then of course, we will get:

a: this is b , b: this is c , c: undefined

Which is totally incorrect, according to our intentions. And the problem only gets worse in more complicated function calls.

We could solve this, by requiring users to always pass 3 arguments, no more, no less, which would be:

foo(null, 'this is b', 'this is c');

But what if we want to make our APIs as beautiful as possible and give our users the convenience of omitting variables?

Enter pragmatik.

Advanced usage

Pragmatik first validates your rules object, to make sure the rules you define are valid according to the way this library works. Parsing varargs is more difficult than you might think, and you have to settle on a good strategy.

Pragmatik uses types ('function','object','string') as a building block for determining if you passed in the expected variable at the given argument index.