Need help with api-check?
Click the “chat” button below for chat support from the developer who created it, or find similar developers for support.

About the developer

kentcdodds
195 Stars 26 Forks MIT License 162 Commits 5 Opened issues

Description

VanillaJS version of ReactJS propTypes

Services available

!
?

Need anything else?

Contributors list

# 1,193
JavaScr...
Babel
reactjs
ecmascr...
143 commits
# 457,631
PHP
HTML
1 commit
# 22,259
eslint-...
lodash
elm
test-fr...
1 commit
# 353,560
Python
Shell
HTML
auth
1 commit

api-check

bower version npm version npm downloads Build Status Code Coverage Gitter

Sponsor

It's like ReactJS

propTypes
without React. Actually, it's very heavily inspired by this concept. It's purpose is for normal JavaScript functions rather than just React Components.

Demo Screenshot

Installation

$ npm i -S api-check
or
$bower i -S api-check

api-check utilizes UMD, so you can:

var apiCheck = require('api-check')(/* your custom options, checkers*/);

Also available as an AMD module or as

apiCheck
on global

Example

Note, there are a bunch of tests. Those should be instructive as well.

var myApiCheck = require('api-check')({
  /* config options */
  output: {
    prefix: 'app/lib Name',
    suffix: 'Good luck!',
    docsBaseUrl: 'http://www.example.com/error-docs#'
  },
  verbose: false
}, {
  /* custom checkers if you wanna */
});

// given we have a function like this: function foo(bar, foobar) { // we can define our api as the first argument to myApiCheck.warn myApiCheck.warn([myApiCheck.number, myApiCheck.arrayOf(myApiCheck.string)], arguments); // do stuff } // the function above can be called like so: foo(3, ['a','b','c']);

// if it were called like so, a descriptive warning would be logged to the console foo('whatever', false);

// here's something a little more complex (this is what's in the screenshot and the demo) var myCheck = require('api-check')({ output: { prefix: 'myApp', suffix: 'see docs -->', docsBaseUrl: 'http://example.com/error-descriptions#' } }); function doSomething(person, options, callback) { myCheck.warn([ // you can also do myCheck.throw to throw an exception myCheck.shape({ name: myCheck.shape({ first: myCheck.string, last: myCheck.string }), age: myCheck.number, isOld: myCheck.bool, walk: myCheck.func, ipAddress: function(val, name, location) { if (!/(\d{1,3}.){3}\d{1,3}/.test(val)) { return myCheck.utils.getError(name, location, 'ipAddress'); } }, childrenNames: myCheck.arrayOf(myCheck.string).optional }), myCheck.any.optional, myCheck.func ], arguments, { prefix: 'doSomething', suffix: 'Good luck!', urlSuffix: 'dosomething-api-check-failure' });

// do stuff }

var person = { name: { first: 'Matt', last: 'Meese' }, age: 27, isOld: false, ipAddress: '127.0.0.1', walk: function() {} }; function callback() {} var options = 'whatever I want because it is an "any" type';

console.log('Successful call'); doSomething(person, options, callback);

console.log('Successful call (without options)'); doSomething(person, callback); //

Differences from React's propTypes

Differences in Supported Types noted below with a *

  • All types are required by default, to set something as optional, append
    .optional
  • checkApi.js does not support
    element
    and
    node
    types
  • checkApi.js supports a few additional types
  • object
    fails on null. Use
    object.nullOk
    if you don't want that

Similarities to React's propTypes

This project was totally written from scratch, but it (should) support the same api as React's

propTypes
(with the noted difference above). If you notice something that functions differently, please file an issue.

apiCheck(), apiCheck.warn(), and apiCheck.throw()

These functions do the same thing, with minor differences. In both the

warn
and
throw
case, a message is generated based on the arguments that the function was received and the api that was defined to describe what was wrong with the invocation.

In all cases, an object is returned with the following properties:

argTypes (arrayOf[Object])

This is an array of objects representing the types of the arguments passed.

apiTypes (arrayOf[Object])

This is an object representing the types of the api. It's a whole language of its own that you'll hopefully get after looking at it for a while.

failed (boolean)

Will be false when the check passes, and true when it fails

passed (boolean)

Will be true when the check passes, and false when it fails

message (string)

If the check failed, this will be a useful message for display to the user. If it passed, this will be an empty string

Also note that if you only have one argument, then the first argument to the

apiCheck
function can simply be the checker function. For example:
apiCheck(apiCheck.bool, arguments);

The second argument can either be an arguments-like object or an array.

Supported types

array

apiCheck.array([]); // 

bool

apiCheck.bool(false); // 

func

apiCheck.func(function() {}); // 

func.withProperties *

Not available in React's

propTypes

var checker = apiCheck.func.withProperties({
  type: apiCheck.oneOfType([apiCheck.object, apiCheck.string]),
  help: apiCheck.string.optional
});
function winning(){}
winning.type = 'awesomeness';
checker(winning); // 

number

apiCheck.number(423.32); // 

object *

null
fails, use
object.nullOk
to allow null to pass
apiCheck.object({}); // 

object.nullOk *

Not available in React's

propTypes

apiCheck.object.nullOk({}); // 

emptyObject *

Not available in React's

propTypes

apiCheck.emptyObject({}); // 

string

apiCheck.string('I am a string!'); // 

range

apiCheck.range(0, 10)(4); // 

greaterThan

apiCheck.greaterThan(100)(200); // 

lessThan

apiCheck.lessThan(100)(50); // 

instanceOf

apiCheck.instanceOf(RegExp)(new RegExp); // 

oneOf

apiCheck.oneOf(['Treek', ' Wicket Wystri Warrick'])('Treek'); // 

oneOfType

apiCheck.oneOfType([apiCheck.string, apiCheck.object])({}); // 

arrayOf

apiCheck.arrayOf(apiCheck.string)(['Huraga', 'Japar', 'Kahless']); // 

typeOrArrayOf *

Not available in React's

propTypes

Convenience checker that combines

oneOfType
with
arrayOf
and whatever you specify. So you could take this:
apiCheck.oneOfType([
  apiCheck.string, apiCheck.arrayOf(apiCheck.string)
]);

with

apiCheck.typeOrArrayOf(apiCheck.string);

which is a common enough use case to justify the checker.

apiCheck.typeOrArrayOf(apiCheck.string)('string'); // 

objectOf

apiCheck.objectOf(apiCheck.arrayOf(apiCheck.bool))({a: [true, false], b: [false, true]}); // 

shape *

Note: React

propTypes
does support
shape
, however it does not support the
strict
option

If you add

.strict
to the
shape
, then it will enforce that the given object does not have any extra properties outside those specified in the
shape
. See below for an example...
apiCheck.shape({
  name: checkers.shape({
    first: checkers.string,
    last: checkers.string
  }),
  age: checkers.number,
  isOld: checkers.bool,
  walk: checkers.func,
  childrenNames: checkers.arrayOf(checkers.string)
})({
  name: {
    first: 'Matt',
    last: 'Meese'
  },
  age: 27,
  isOld: false,
  walk: function() {},
  childrenNames: []
}); // 

Example of

strict
var strictShape = apiCheck.shape({
  cookies: apiCheck.bool,
  milk: apiCheck.bool,
  popcorn: apiCheck.bool.optional
}).strict; // 

Note, you can also append

.optional
to the
.strict
(as in:
apiCheck.shape({}).strict.optional
)

shape.onlyIf *

Not available in React's

propTypes

This can only be used in combination with

shape
apiCheck.shape({
  cookies: apiCheck.shape.onlyIf(['mint', 'chips'], apiCheck.bool)
})({cookies: true, mint: true, chips: true}); // 

shape.ifNot *

Not available in React's

propTypes

This can only be used in combination with

shape
apiCheck.shape({
  cookies: apiCheck.shape.ifNot('mint', apiCheck.bool)
})({cookies: true}); // 

requiredIfNot *

Not available in React's

propTypes

This can only be used in combination with

shape
checker = checkers.shape({
  foobar: checkers.shape.requiredIfNot(['foobaz', 'baz'], checkers.bool),
  foobaz: checkers.object.optional,
  baz: checkers.string.optional,
  foo: checkers.string.optional
});
checker({
  foo: [1, 2],
  foobar: true
}); // 
all

Not available in React's

propTypes

This can only be used in combination with

shape.requiredIfNot
checker = checkers.shape({
  foobar: checkers.shape.requiredIfNot.all(['foobaz', 'baz'], checkers.bool),
  foobaz: checkers.object.optional,
  baz: checkers.string.optional,
  foo: checkers.string.optional
});
checker({
  foo: [1, 2]
}); // 

args *

Not available in React's

propTypes

This will check if the given item is an

arguments
-like object (non-array object that has a length property)
function foo(bar) {
  apiCheck.args(arguments); // 

any

apiCheck.any({}); // 

null

apiCheck.null(null); // 

Custom Types

You can specify your own type. You do so like so:

var myCheck = require('api-check')({
  output: {prefix: 'myCheck'}
});

function ipAddressChecker(val, name, location) { if (!/(\d{1,3}.){3}\d{1,3}/.test(val)) { return apiCheck.utils.getError(name, location, ipAddressChecker.type); } }; ipAddressChecker.type = 'ipAddressString';

function foo(string, ipAddress) { myCheck.warn([ myCheck.string, ipAddressChecker ], arguments); }

Then, if you invoked that function like this:

foo('hello', 'not-an-ip-address');

It would result in a warning like this:

myCheck apiCheck failed! `Argument 1` passed, `value` at `Argument 2` must be `ipAddressString`

You passed: [ "hello", "not-an-ip-address" ]

With the types: [ "string", "string" ]

The API calls for: [ "String", "ipAddressString" ]

There's actually quite a bit of cool stuff you can do with custom types checkers. If you want to know what they are, look at the tests or file an issue for me to go document them. :-)

apiCheck.utils

When writing custom types, you may find the

utils
helpful. Please file an issue to ask me to improve documentation for what's available. For now, check out
api-check-utils.test.js

Customization

Note, obviously, these things are specific to

apiCheck
and not part of React
propTypes

When you create your instance of

apiCheck
, you can configure it with different options as part of the first argument.

config.output

You can specify some extra options for the output of the message.

var myApiCheck = require('api-check')({
  output: {
    prefix: 'Global prefix',
    suffix: 'global suffix',
    docsBaseUrl: 'https://example.com/errors-and-warnings#'
  },
  verbose: false, // 

You can also specify an

output
object to each
apiCheck()
,
apiCheck.throw()
, and
apiCheck.warn()
request:
myApiCheck(apiCheck.bool, arguments, {
  prefix: 'instance prefix:',
  suffix: 'instance suffix',
  urlSuffix: 'example-error-additional-info'
});

A failure with the above configuration would yield something like this:

Global prefix instance prefix {{error message}} instance suffix global suffix https://example.com/errors-and-warnings#example-error-additional-info

As an alternative to

urlSuffix
, you can also specify a
url
:
myApiCheck(apiCheck.bool, arguments, {
  url: 'https://example.com/some-direct-url-that-does-not-use-the-docsBaseUrl'
});

getErrorMessage

This is the method that apiCheck uses to get the message it throws or console.warns. If you don't like it, feel free to make a better one by simply:

apiCheck.getErrorMessage = function(api, args, output) {/* return message */}

handleErrorMessage

This is the method that apiCheck uses to throw or warn the message. If you prefer to do your own thing, that's cool. Simply

apiCheck.handleErrorMessage = function(message, shouldThrow) { /* throw or warn */ }

Disable apiCheck

It's a good idea to disable the apiCheck in production. You can disable your own instance of

apiCheck
as part of the
options
, but it's probably just better to disable
apiCheck
globally. I recommend you do this before you (or any of you dependencies) create an instance of
apiCheck
. Here's how you would do that:
var apiCheck = require('api-check');
apiCheck.globalConfig.disabled = true;

Credits

This library was written by Kent C. Dodds. Again, big credits go to the team working on React for thinking up the api. This library was written from scratch, but I'd be lying if I didn't say that I referenced their functions a time or two.

We use cookies. If you continue to browse the site, you agree to the use of cookies. For more information on our use of cookies please see our Privacy Policy.