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

pico-type

v1.0.0

Published

A tiny custom schema checker for js

Downloads

2

Readme

🛂 pico-type

A tiny custom interface checker for js. Easily describe the shape of your data and validate it.

install

npm install pico-type

Example

const {or, opt, is, ensure} = require('pico-type');

const UserType = {
	id         : types.uuid,
	email      : /^.+@.+\..+$/,
	post_count : Number,
	tags       : [String],
	posts : [{
		title : String,
		read : Function
	}],
	age      : (val)=>0 < val && val < 150,
	flagged  : opt(Boolean),
	created  : or(Number, Date),
	location : types.geo,
	meta     : '*'
}

const user = {...};

if(is(UserType, user)) console.log('is a user!');

ensure(UserType, user); //Throws if not a user

const isUserType = is.bind(null, UserType);

isUserType(user);  // true/false checker for UserTypes now!

Features

  • Interfaces are just simple objects, arrays, functions, or Native primitives
  • Under 100 lines of code
  • Able to disable run-time checks for production/performance
  • Can use .cast() to create proxies to do assertion-time checks

pico-type gives you tools for checking data strucutres against interfaces to see if they pass. Define the shape of your data using Native types, functions, arrays, objects, or regex.

How To Use

You define interfaces using a combination of the below types:

Wildcard

If your interface is exactly '*', picotype will pass regardless of value.

ensure('*', 'foo')

Natives

Any Native Type in js can be used: String, Number, Function, Date, Object, Array, etc.

const { ensure } = require('pico-type');

ensure(String, "Oh hello");
ensure(Object, {a : true});
ensure(Number, 500);

Regex

You can use a Regular Expression as a type, and pico-type will use it to test against the value.

const { ensure } = require('pico-type');

ensure(/^.+@.+\..+$/, '[email protected]');
ensure(/^\+?(\d.*){3,}$/, '613-555-0106');

Array

If you provide an array as a type, pico-type will check that the value is an array, and use the first element of the interface array as the interface for every element that is in the value's corresponding array

const { ensure } = require('pico-type');

ensure([String], ['these', 'are', 'tags']);
ensure([{ ok : Boolean }], [{ ok : true}, { ok : false}]);

Objects

Providing an object as a type will iterate over each key, and uses it's value as a interface for the value's corresponding key.

const { ensure } = require('pico-type');

ensure({ ok : Boolean, foo : Number}, {ok : true, foo : 6});

//These can be nested
ensure({
	nested : {
		obj : String
	}
}, { nested : { obj : 'doot'}});

This also lets you easily combine interfaces together.


const AgeType = (val)=>0<val && val<150
const TagType = {
	tag : String,
	ts : or(Date, Number)
};

const UserType = {
	name: String,
	age : AgeType,
	tags : [TagType]
}

const UserGroupType = {
	id : String,
	users : [UserType],
};

Function

Any function can be used as a type. pico-type will call the function while validating. If the function returns exactly true or undefined it's considered a pass. If it returns anything else (or throws an error), it's considered a fail and pico-type will use the returned value as the error message.

const { ensure } = require('pico-type');

const ageType = (val)=>0 < val && val < 150
ensure(ageType, 36);

//Picotype passes the arg name as the second paremter, which you can use in your error messages.
const geoType = (val, name)=>{
	if(typeof val.lat !== 'number') return `${name}.lat is not a number`;
	if(typeof val.lng !== 'number') return `${name}.lng is not a number`;
	if(val.lat < -90 || val.lat > 90) return `${name}.lat has an invalid range`;
	if(val.lng < -180 || val.lng > 180) return `${name}.lng has an invalid range`;
}
ensure(geoType, {lat: -29.83249, lng: -50.66126});

API

.ensure(interface, value) -> true / Error

Returns true if the value passes the interface, otherwise throws with an error explaining which field invalidates the interface and why.

.is(interface, value) -> true / false

Returns true if the value matches the interface, false if it doesn't

.enable() / .disable()

Enables or disables pico-type's checks. This makes .ensure(), .is(), .wrap(), and .cast() perform fast no-ops

.wrap(parameterInterfaces, func, returnInterface) -> function

Wraps a given function in both parameter and return checks, returns a new veried function.

parameterInterfaces is an array of interfaces applied to each argument

const {wrap} = require('pico-type');
const GeoType = {/*...*/}


const geoDistance = wrap(
	[GeoType, GeoType],
	(point1,    point2)=>{/*...*/},
	Number
);

//can leave either parameter or return interface blank as well
const noChecks = wrap(null, (a,b,c)=>{}, null);

.cast(interface, [initVal])

Creates a Proxied object that whenever a property is set on it, it checks against the provided interface.

let tempUser = cast({
	name : String,
	age : AgeType
});

tempUser.name = true; //Throws an error!
tempUser.age = -2.3452; //Also throws an error!

You can also pass an initial value into the proxied Object as the second parameter. Under the hood, pico-type will skip checks on cast'd objects if they are combine in other checks, since their are guaranteed to be passing!

Utils

.or(...types) -> function(value)

Returns a validation function that passes if the value passes any one of the provided types.

const {or, ensure} = require('pico-type');

const DateType = or(Number, Date);
ensure(DateType, new Date());

.opt(type) -> function(value)

Returns a validation function that passes if the value passes the type or is undefined

const {opt, ensure} = require('pico-type');

const BoolOrNothing = opt(Boolean);