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 🙏

© 2026 – Pkg Stats / Ryan Hefner

loch

v0.1.6

Published

loch down your API before the data hits your models

Readme

Loch Down Your API

Loch offers a way to enforce your API at a level above your model, and return sane, helpful errors at the same time.

Specify, using data what you expect to get from the users of your API, and tell them off when they don't do it right.

Simple Usage

For example, you might require the user to give a name with the current request, but they can choose whether or not to give an age:

{ name: true, age: false }

Or you might require that they give a username with at least 5 chars, as well as a sex which may be either male, female, or other.

{ username: [true,
             function(val, key) { if (val.length > 4) return true;
                                  else return key + " must be >= 5"}],
  sex: [true, ['male', 'female', 'other']]}

Then validate the request parameters like so:

validates(validationMap, requestParams)

Which returns true if the request is valid, or else returns a map of keys and errors if the request is not valid.

There are many built-in validators, and anything that is not built in can easily be added (as seen with the username validation above).

You can find extensive documentation below.

There is more documentation to come on auxillary functions, as well as more funtionality that is currently in the works including whitelisting response maps, and more flexible built-in validation functions. TBC.

Documentation

This is a copy-paste of the docs included in the source; the source is meant to be easy-to-read as well.

validation(validation, requestBody)

Takes a validation object, validation, which is a map (which may be nested) of keys to requirements, and a request body (a map of request parameters).

requestBody must be in the form of nested (or not) objects. Arrays are not expected or handled (this is meant for use with HTTP-based APIs, for now).

Returns true if the params meet the specification of validation otherwise returns an object containing the parameters which caused errors.

Validation Maps

Requirements are tuples (arrays of length 2) of [required::Boolean, validator::function]. An example validation map might look like the follow.

{name: [true, atLeastOfLength(5)],
 age: false,
 parents: [false, { mother: false, father: false }]
 ssn: [false, function(o) { return containsNDigits(9); }]}

Validators (validation functions)

A validation function takes in (val, key), and returns true if the value is valid, else returns an error string (or false, for a default error message).

As an alternative to providing a validation function, you can say with true or false whether the key is required (above with age, mother, father):

{ key: required::Boolean }

In addition to providing validation function, the second element in the tuple may be another validation map, to which the rules above will be applied recursively (see parents key above).

If the validation map is empty, all parameters will be allowed within it. If you have certain requirements inside of that map (i.e. properties MUST include some key and value, and then may allow whatever others), use a helper function or create your own function.

Instead of a validation function you may use an array of values with which the value being validated will be tested for inclusion within. For example, if a value must be either 'true' or 'false', you could use:

{ key: [true, ["true", "false"]] }

Which is functionally equivalent to:

{ key: [true, function(o) { return _.contains(['true', 'false'], o)}] }

Errors

The error object which is returned when validation fails will look like the following:

{ errorKey: "error message", ... }

For example:

{ name: "name is required",
  ssn: "ssn must have exactly 9 digits",
  parents: { sister: "sister is not a valid parameter" } }

Or, if the value of parents had been a string instead of an object:

{ parents: "parents must be an object" }

As you can see, the 'ssn' error is very informative. That is because of the way validation function are defined. Validation function must return true if the value is valid, else it must return a function which takes a key (the key being validated), and returns a string which will be used as the error message.

false may be used instead of a string, but then the default error message listed for the param will be "{keyname} is not valid".

If a key is required and is not provided, the default error message is "{keyname} is required".

If a value is supposed to be found in an array (using the array shortcut notation above), the default error message is "{keyname} must be one of {*array}".

If there is a key in the requestBody that does not appear in the validation map, it will result in default error message "{keyname} is not accepted".

Tests

A test suite may be found in tests. It should be run with vows. (I use vows --spec, because it's helpful).

Tests are also a good source of example usage.

Contributing

Contributions are much appreciated. Please issue a pull request with a description of your addition, along with rational behind it, and ideally some tests. Please make sure the tests pass. Also, you may want to run readyjs (or, rather, jshint) on the code to check for semicolons etc. I ignore some of the sillier output; so can you. But, no breaking lochs, please.

Deps

loch uses underscore. Underscore is lovely.