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

argument-validator

v0.1.0

Published

Simple Argument Validator for JavaScript

Downloads

4,113

Readme

Argument Validator

Simple JavaScript Argument Validator.

Build Status npm npm

NPM

Fail First

Argument Validator main principle is Fail First, we don't want to send wrong values through all our code. Although, we don't want to throw an exception to everything we get from user input, but we do want to validate(and throw first) when we receive something unexpected in our core functions.

Sugar - We expose the is* and has* functions, it can be handy.

Note - By default all validations check also for null/empty, e.g. ArgumentValidator.array([]) will throw because is an empty array, to validate only type use type() or the *OrEmpty() functions, e.g. ArgumentValidator.arrayOrEmpty([])


About

We all know that JavaScript has no type checking, also we know that's not a good practice to throw errors with Node.JS, because it's async and we don't want to take down our app, do some global handler or something fancy. but...

Inside our core, when we receive an argument the most part of time we expect that argument is in such type, so we can perform methods of that type (substring/slice/toFixed...) and if it's not in correct type it will throw an ugly TypeError exception, if it's in a nested function will be a rabbit hole try to figure out where that value come at first.

A lot of languages has this kind of checking internally, but we're talking about JavaScript here. :)

Imagine this cenario;


function Rabbit (name) {
  this.name = name;
}

function Hole (rabbit) {
  this.rabbit = rabbit;
}

Hole.prototype.firstRabbitLetter = function () {
  return this.rabbit.name.substring(0, 1);
};

var h = new Hole(new Rabbit());
console.log(h.firstRabbitLetter());

With that code, we'll have this stack trace in Node.JS:

argument-validator/argument-validator.js:145
        return this.rabbit.name.substring(0, 1);
                                ^
TypeError: Cannot call method 'substring' of undefined
    at Hole.firstRabbitLetter (argument-validator/argument-validator.js:145:33)
    at Object.<anonymous> (argument-validator/argument-validator.js:149:19)
    at Object.<anonymous> (argument-validator/argument-validator.js:150:4)
    at Module._compile (module.js:456:26)
    at Object.Module._extensions..js (module.js:474:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:312:12)
    at Function.Module.runMain (module.js:497:10)
    at startup (node.js:119:16)
    at node.js:906:3

We know that our rabbit inside a Hole class has an undefined name, and the method firstRabbitLetter is trying to get it's first letter, but...

How it get there without a rabbit name? Did we pass an undefined name in the constructor or it lost the name property a long the way? Where is the declaration of new Hole() and new Rabbit() ?

Our stack trace doesn't give us that, so the way to figure out would be something like put a breakpoint in firstRabbitLetter and dig it.

Wouldn't be better if we throw first at the new Rabbit(), so we don't need to go that deep?

Try that:


function Rabbit (name) {
  ArgumentValidator.string(name, 'name');
  this.name = name;
}
/* .... */
function Hole(rabbit) {
  ArgumentValidator.instanceOf(Rabbit, rabbit, 'rabbit');
  this.rabbit = rabbit;
}
/* .... */

Stack trace:

argument-validator/argument-validator.js:6
        throw new Error(msg);
              ^
Error: Invalid string value: undefined
Argument name: name
    at error (argument-validator/argument-validator.js:6:15)
    at Object.string (argument-validator/argument-validator.js:16:24)
    at new Rabbit (argument-validator/argument-validator.js:137:11)
    at Object.<anonymous> (argument-validator/argument-validator.js:149:22)
    at Object.<anonymous> (argument-validator/argument-validator.js:151:4)
    at Module._compile (module.js:456:26)
    at Object.Module._extensions..js (module.js:474:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:312:12)
    at Function.Module.runMain (module.js:497:10)

In that case it's not making a huge difference, but at least we have sure that our undefined is coming from Rabbit constructor. In more nested cenarios it will make more difference, that small example is only for you have a feeling of what we're talking about here.

Bonus - Using this practice let your code more readable, everyone who reads the code will know exactly what arguments it expects.

Get it

npm:

npm install argument-validator

bower:

bower install argument-validator

unix:

wget https://raw.githubusercontent.com/Deividy/argument-validator/master/argument-validator.js

Methods


notNull / isNotNull

ArgumentValidator.notNull(value, optionalArgumentName);
ArgumentValidator.isNotNull(value);

instanceOf / isInstanceOf

ArgumentValidator.instanceOf(Class, value, optionalArgumentName);
ArgumentValidator.isInstanceOf(Class, value);

type / isType

ArgumentValidator.type(type, value, optionalArgumentName);
ArgumentValidator.isType(type, value);

boolean / isBoolean

ArgumentValidator.boolean(value, optionalArgumentName);
ArgumentValidator.isBoolean(value);

stringOrEmpty / isStringOrEmpty

ArgumentValidator.stringOrEmpty(value, optionalArgumentName);
ArgumentValidator.isStringOrEmpty(value);

string / isString

ArgumentValidator.string(value, optionalArgumentName);
ArgumentValidator.isString(value);

Validate agains type, simple call to Object.prototype.toString and check if "[object " + type + "]".

(function () {
    ArgumentValidator.type('Date', new Date());
}).should.not.throw();

(function () {
    ArgumentValidator.type('Date', '223');
}).should.throw();
ArgumentValidator.isType('Date', new Date()).should.be.true;
ArgumentValidator.isType('Date', '[object Date]').should.be.false;
ArgumentValidator.isType('Number', 123).should.be.true;
ArgumentValidator.isType('Number', '123').should.be.false;

number / isNumber

ArgumentValidator.number(value, optionalArgumentName);
ArgumentValidator.isNumber(value);

Validate against type Number, against isInfinite and isNaN.

(function () {
    ArgumentValidator.number(5);
    ArgumentValidator.number(4/'2');
    ArgumentValidator.number(12.5235134);
}).should.not.throw();

(function () { ArgumentValidator.number('5'); }).should.throw();
(function () { ArgumentValidator.number(1/0); }).should.throw();
(function () { ArgumentValidator.number(1/'A'); }).should.throw();
ArgumentValidator.isNumber(5).should.be.true;
ArgumentValidator.isNumber(12.5235134).should.be.true;
ArgumentValidator.isNumber(4 / '2').should.be.true;
ArgumentValidator.isNumber('4' / 2).should.be.true;
ArgumentValidator.isNumber('5').should.be.false;
ArgumentValidator.isNumber(1/0).should.be.false;

arrayOrEmpty / isArrayOrEmpty

ArgumentValidator.arrayOrEmpty(value, optionalArgumentName);
ArgumentValidator.isArrayOrEmpty(value);

array / isArray

ArgumentValidator.array(value, optionalArgumentName);
ArgumentValidator.isArray(value);

arrayOfNumbers / isArrayOfNumbers

ArgumentValidator.arrayOfNumbers(value, optionalArgumentName);
ArgumentValidator.isArrayOfNumbers(value);

arrayOfObjects / isArrayOfObjects

ArgumentValidator.arrayOfObjects(value, optionalArgumentName);
ArgumentValidator.isArrayOfObjects(value);

objectOrEmpty / isObjectOrEmpty

ArgumentValidator.objectOrEmpty(value, optionalArgumentName);
ArgumentValidator.isObjectOrEmpty(value);

object / isObject

ArgumentValidator.object(value, optionalArgumentName);
ArgumentValidator.isObject(value);

function / isFunction

ArgumentValidator.function(value, optionalArgumentName);
ArgumentValidator.isFunction(value);

json / isJson

ArgumentValidator.json(value, optionalArgumentName);
ArgumentValidator.isJson(value);

jsonString / isJsonString

ArgumentValidator.jsonString(value, optionalArgumentName);
ArgumentValidator.isJsonString(value);

keys / hasKeys

ArgumentValidator.keys(value, [ keys ], optionalArgumentName);
ArgumentValidator.hasKeys(value, [ keys ]);

keysWithNumber / hasKeysWithNumber

ArgumentValidator.keysWithNumber(value, [ keys ], optionalArgumentName);
ArgumentValidator.hasKeysWithNumber(value, [ keys ]);

numberKeys / hasNumberKeys

ArgumentValidator.numberKeys(value, [ keys ], optionalArgumentName);
ArgumentValidator.hasNumberKeys(value, [ keys ]);

keysWithString / hasKeysWithString

ArgumentValidator.keysWithString(value, [ keys ], optionalArgumentName);
ArgumentValidator.hasKeysWithString(value, [ keys ]);

stringKeys / hasStringKeys

ArgumentValidator.stringKeys(value, [ keys ], optionalArgumentName);
ArgumentValidator.hasStringKeys(value, [ keys ]);

keysWithObject / hasKeysWithObject

ArgumentValidator.keysWithObject(value, [ keys ], optionalArgumentName);
ArgumentValidator.hasKeysWithObject(value, [ keys ]);

objectKeys / hasObjectKeys

ArgumentValidator.objectKeys(value, [ keys ], optionalArgumentName);
ArgumentValidator.hasObjectKeys(value, [ keys ]);

keysWithStringOrEmpty / hasKeysWithStringOrEmpty

ArgumentValidator.keysWithStringOrEmpty(value, [ keys ], optionalArgumentName);
ArgumentValidator.hasKeysWithStringOrEmpty(value, [ keys ]);

stringOrEmptyKeys / hasStringOrEmptyKeys

ArgumentValidator.stringOrEmptyKeys(value, [ keys ], optionalArgumentName);
ArgumentValidator.hasStringOrEmptyKeys(value, [ keys ]);

keysWithObjectOrEmpty / hasKeysWithObjectOrEmpty

ArgumentValidator.keysWithObjectOrEmpty(value, [ keys ], optionalArgumentName);
ArgumentValidator.hasKeysWithObjectOrEmpty(value, [ keys ]);

objectOrEmptyKeys / hasObjectOrEmptyKeys

ArgumentValidator.objectOrEmptyKeys(value, [ keys ], optionalArgumentName);
ArgumentValidator.hasObjectOrEmptyKeys(value, [ keys ]);

More?

Please check specs/ to more examples or read the full code, it's really small.

If you have any suggestion, please don't be shy, fork us or open an issue.