Code Monkey home page Code Monkey logo

api-check's Introduction

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](http://jsbin.com/hibocu/edit?js,console,output))
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); // <-- options is optional

console.log('Failed call (without person)');
doSomething(callback); // <-- this would fail because person is not optional

person.ipAddress = 'Invalid IP Address!!!';

console.log('Failed call (invalid ip address)');
doSomething(person, options, callback); // <-- this would fail because the ipAddress checker would fail

// if you only wish to check the first argument to a function, you don't need to supply an array.

var libCheck = apiCheck(); // you don't HAVE to pass anything if you don't want to.
function bar(a) {
  var errorMessage = libCheck(apiCheck.string, arguments);
  if (!errorMessage) {
    // success
  } else if (typeof errorMessage === 'string') {
    // there was a problem and errorMessage would like to tell you about it
  }
}
bar('hello!'); // <-- success!

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([]); // <-- pass
apiCheck.array(23); // <-- fail

bool

apiCheck.bool(false); // <-- pass
apiCheck.bool('me bool too?'); // <-- fail

func

apiCheck.func(function() {}); // <-- pass
apiCheck.func(new RegExp()); // <-- fail

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); // <--pass

function losing(){}
checker(losing); // <-- fail

number

apiCheck.number(423.32); // <-- pass
apiCheck.number({}); // <-- fail

object *

null fails, use object.nullOk to allow null to pass

apiCheck.object({}); // <-- pass
apiCheck.object([]); // <-- fail
apiCheck.object(null); // <-- fail

object.nullOk *

Not available in React's propTypes

apiCheck.object.nullOk({}); // <-- pass
apiCheck.object.nullOk([]); // <--- false
apiCheck.object.nullOk(null); // <-- pass

emptyObject *

Not available in React's propTypes

apiCheck.emptyObject({}); // <-- pass
apiCheck.emptyObject([]); // <-- fail
apiCheck.emptyObject(null); // <-- fail
apiCheck.emptyObject({"foo": "bar"}) // <-- fail

string

apiCheck.string('I am a string!'); // <-- pass
apiCheck.string([]); // <-- fail

range

apiCheck.range(0, 10)(4); // <-- pass
apiCheck.range(-100, 100)(500); // <-- fail

greaterThan

apiCheck.greaterThan(100)(200); // <-- pass
apiCheck.greaterThan(-10)(-20); // <-- fail
apiCheck.greaterThan(50)('Frogs!'); // <-- fail

lessThan

apiCheck.lessThan(100)(50); // <-- pass
apiCheck.lessThan(-10)(0); // <-- fail
apiCheck.lessThan(50)('Frogs!'); // <-- fail

instanceOf

apiCheck.instanceOf(RegExp)(new RegExp); // <-- pass
apiCheck.instanceOf(Date)('wanna go on a date?'); // <-- fail

oneOf

apiCheck.oneOf(['Treek', ' Wicket Wystri Warrick'])('Treek'); // <-- pass
apiCheck.oneOf(['Chewbacca', 'Snoova'])('Snoova'); // <-- fail

oneOfType

apiCheck.oneOfType([apiCheck.string, apiCheck.object])({}); // <-- pass
apiCheck.oneOfType([apiCheck.array, apiCheck.bool])('Kess'); // <-- fail

arrayOf

apiCheck.arrayOf(apiCheck.string)(['Huraga', 'Japar', 'Kahless']); // <-- pass
apiCheck.arrayOf(
  apiCheck.arrayOf(
    apiCheck.arrayOf(
      apiCheck.number
    )
  )
)([[[1,2,3], [4,5,6], [7,8,9]], [[1,2,3], [4,5,6], [7,8,9]]]); // <-- pass (for realz)
apiCheck.arrayOf(apiCheck.bool)(['a', 'b', 'c']); // <-- fail

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'); // <-- pass
apiCheck.typeOrArrayOf(apiCheck.string)(['array', 'of strings']); // <-- pass
apiCheck.typeOrArrayOf(apiCheck.bool)(['array', false]); // <-- fail
apiCheck.typeOrArrayOf(apiCheck.object)(32); // <-- fail

objectOf

apiCheck.objectOf(apiCheck.arrayOf(apiCheck.bool))({a: [true, false], b: [false, true]}); // <-- pass
apiCheck.objectOf(apiCheck.number)({a: 'not a number?', b: 'yeah, me neither (โ—žโ€ธโ—Ÿ๏ผ›)'}); // <-- fail

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: []
}); // <-- pass
apiCheck.shape({
  mint: checkers.bool,
  chocolate: checkers.bool
})({mint: true}); // <-- fail

Example of strict

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

strictShape({
  cookies: true,
  milk: true,
  popcorn: true,
  candy: true
}); // <-- fail because the extra `candy` property

strictShape({
  cookies: true,
  milk: true
}); // <-- pass because it has no extra properties and `popcorn` is optional

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}); // <-- pass

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

apiCheck.shape({
  cookies: apiCheck.shape.onlyIf('mint', apiCheck.bool)
})({cookies: true}); // <-- fail

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}); // <-- pass

apiCheck.shape({
  cookies: apiCheck.shape.ifNot(['mint', 'chips'], apiCheck.bool)
})({cookies: true, chips: true}); // <-- fail

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
}); // <-- passes

checker({foo: 'bar'}); // <-- fails
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]
}); // <-- fails

checker({
  foo: [1, 2],
  foobar: true
}); // <-- passes

checker({
  foo: [1, 2],
  baz: 'foo'
}); // <-- passes

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); // <-- pass
}
apiCheck.args([]); // <-- fail
apiCheck.args({}); // <-- fail
apiCheck.args({length: 3}); // <-- pass
apiCheck.args({length: 'not-number'}); // <-- fail

any

apiCheck.any({}); // <-- pass
apiCheck.any([]); // <-- pass
apiCheck.any(true); // <-- pass
apiCheck.any(false); // <-- pass
apiCheck.any(/* seriously, anything, except undefined */); // <-- fail
apiCheck.any.optional(/* unless you specify optional :-) */); // <-- pass
apiCheck.any(3); // <-- pass
apiCheck.any(3.1); // <-- pass
apiCheck.any(3.14); // <-- pass
apiCheck.any(3.141); // <-- pass
apiCheck.any(3.1415); // <-- pass
apiCheck.any(3.14159); // <-- pass
apiCheck.any(3.141592); // <-- pass
apiCheck.any(3.1415926); // <-- pass
apiCheck.any(3.14159265); // <-- pass
apiCheck.any(3.141592653); // <-- pass
apiCheck.any(3.1415926535); // <-- pass
apiCheck.any(3.14159265359); // <-- pass
apiCheck.any(jfio,.jgo); // <-- Syntax error.... เฒ _เฒ 

null

apiCheck.null(null); // <-- pass
apiCheck.null(undefined); // <-- fail
apiCheck.null('hello'); // <-- fail

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, // <-- defaults to false
  disabled: false // <-- defaults to false, set this to true in production
});

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.

api-check's People

Contributors

greenkeeperio-bot avatar jfmengels avatar llwt avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

api-check's Issues

Variable number of arguments

It would be useful to define a check for a variable length of arguments of the same type. A logger function for example could take multiple strings as arguments:

log('one string')
log('two ', 'strings')

Do you think this will be possible in the near future, or is it already possible and I just don't get it?

Make the "you passed" not so hard to read

This is what it looks like in one app I tried it in:

You passed: `["{\"name\":\"String\",\"template\":\"String\"}","{\"name\":\"String\",\"template\":\"String\"}","{\"templateUrl\":\"String\"}","{\"name\":\"String\",\"defaultOptions\":\"{}\"}"]`

It could be much worse if much more were passed. Figure out a way to make it look nice like the example of what can be passed in.

Checker enhancement: instanceOf accept array

Would like to be able to do this:

apiCheck.instanceOf([
  Foo, Bar, Baz
]);

Right now I have to do:

apiCheck.oneOfType([
  apiCheck.instanceOf(Foo),
  apiCheck.instanceOf(Bar),
  apiCheck.instanceOf(Baz)
]);

Documentation incorrect for getErrorMessage

Docs say:

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 */}

But, it appears that getErrorMessage() actually is a function(api, args, messages, output).

apiCheck.js vs. api-check.js

With a recent code update, the name of the distribution JS file was changed from 'apiCheck.js' to 'api-check.js'.

For those of us attempting to update to the newest version of apiCheck - this caused some serious 'consternation' on our part... Please consider updating the documentation and/or the project name itself (kentcdodds/apiCheck.js) - as it's now misleading and can cause some serious hair-pulling to occur before consulting with you about the change...

Thanks!

Using api-check methods within custom checker

Hey @kentcdodds,

I was hoping I could use api-check methods within a custom checker. Perhaps something sort of like this:

   randomData: function (val, name, location) {
        ac.throw([
            ac.shape({
                "name": ac.string,
                "site": ac.string,
                "forwardRegex": ac.string,
                "reverseRegex": ac.string,
                "cutType": ac.number,
                "dsForward": ac.number,
                "dsReverse": ac.number,
                "usForward": ac.number,
                "usReverse": ac.number
            })
        ], val);
    },

But I wasn't sure how to go about doing so exactly..
Is there a good way of doing this?

Thanks for all your time! It is much appreciated!
Thomas

Make the output only show what's relevant

Right now, if I have a deep shape that has a lot of optional fields it prints EVERYTHING to the user and that's confusing if they normally only specify a few fields. Would be really nice if it only showed the definition for the fields they specified and required fields.

Path in bower.json not valid - case-sensitivity

I have problem in my project using bower generated index.html because in bower.json in apiCheck there is

"main": "dist/apicheck.js",

but the actual file in dist directory is apiCheck.js

please correct the case (it would be best to change the name of file in dist, not in bower.json, better to keep it lowercase)

`strict` shape constraint does not seem to be working

The docs show this example:

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

strictShape.strict = true; // <-- that!

strictShape({
  cookies: true,
  milk: true,
  popcorn: true,
  candy: true
}); // <-- fail because the extra `candy` property

strictShape({
  cookies: true,
  milk: true
}); // <-- pass because it has no extra properties and `popcorn` is optional

But strict doesn't seem to be doing anything. Both objects pass validation.

See http://jsbin.com/cerapo/1/edit?js,console

Interoperability with react proptypes?

Hey there, just wondering if it would be possible to do something like this:

var ac = require('ve-api-check');
import React, {PropTypes} from 'react';
let Comp = React.createClass({
    propTypes: {
        width: ac.number,

From the simple test I did it didn't seem to be working. Just double checking that this is the case. It would be nice if they were interoperable, especially for custom checkers so I wouldn't have to duplicate work.

Thanks for all the hard work you've put into this project! It is working great!

checking non-arguments

API is pretty clunky if you want to use api-check outside validation of arguments, where everything seems to need to be wrapped in an array.

var apiCheck = require('api-check')()
apiCheck.throw([apiCheck.string], ['abc'])

Currently, the example below that is without the use of array wrappers does not work. I'd like to propose that it should. In addition note the error it does produce is gargantuan and not very insightful.

var apiCheck = require('api-check')()
apiCheck.throw(apiCheck.string, 'abc')
Error: apiCheck apiCheck failed! `Argument 1` passed, `value` at `Argument 2` must be `oneOfType[function arguments, Array]`, `Argument 3 (optional)` passed

You passed:
[
  {
    "1": "abc"
  }
]

With the types of:
[
  {
    "0": "Function",
    "1": "String",
    "2": "undefined"
  }
]

The API calls for:
[
  {
    "__apiCheckData": {
      "optional": false,
      "type": "typeOrArrayOf"
    },
    "typeOrArrayOf": {
      "__apiCheckData": {
        "strict": false,
        "optional": false,
        "type": "func.withProperties"
      },
      "func.withProperties": {
        "type": {
          "__apiCheckData": {
            "optional": true,
            "type": "oneOfType"
          },
          "oneOfType": [
            "String",
            "checkerTypeType"
          ]
        },
        "displayName": "String (optional)",
        "shortType": "String (optional)",
        "notOptional": "Boolean (optional)",
        "childrenCheckers": {
          "__apiCheckData": {
            "optional": true,
            "type": "arrayOf"
          },
          "arrayOf": "String"
        }
      }
    }
  },
  {
    "__apiCheckData": {
      "optional": false,
      "type": "oneOfType"
    },
    "oneOfType": [
      "function arguments",
      "Array"
    ]
  },
  {
    "__apiCheckData": {
      "strict": true,
      "optional": true,
      "type": "shape"
    },
    "shape": {}
  }
]
    at Function.handleErrorMessage (/Users/timoxley/Projects/tests/node_modules/api-check/dist/apiCheck.js:224:14)
    at checkApiCheckApi (/Users/timoxley/Projects/tests/node_modules/api-check/dist/apiCheck.js:210:17)
    at apiCheck (/Users/timoxley/Projects/tests/node_modules/api-check/dist/apiCheck.js:171:6)
    at Function.apiCheckWrapper [as throw] (/Users/timoxley/Projects/tests/node_modules/api-check/dist/apiCheck.js:216:21)
    at repl:1:16
    at REPLServer.self.eval (repl.js:110:21)
    at Interface.<anonymous> (repl.js:239:12)
    at Interface.emit (events.js:95:17)
    at Interface._onLine (readline.js:203:10)
    at Interface._line (readline.js:532:8)

New Checker: all

Something like this:

function Foo() {
}

var checker = apiCheck.all([
  apiCheck.instanceOf(Foo),
  apiCheck.shape({
    bar: apiCheck.string
  })
]);

var foo = new Foo();
checker(foo); // <-- returns error

foo.bar = 'baz';
checker(foo); // <-- returns undefined

New Checker: nothing

So the expected way to make sure that a property does not exist is to just not include it in the apiCheck specification, correct? But I think there might be a use case for having a type called nothing that will fail if the user provides the property and pass if they don't.

To use an example from formly, I've written a custom formly type that doesn't make use of formly's key property. To make sure users of the type don't expect it to use the key property I'd like to override the base formly apiCheck that makes sure key is string and instead make sure it's not included.

Honestly, I'm not even sure the override would work with formly. But if it would, would there be a use case for a nothing type? Or am I missing something?

export an instance by default

Current setup requires user to reconfigure apiCheck in every file they use it in. I feel that use-cases will not need such flexibility and a single instance is probably preferable.

I'd like to suggest the default export be an apiCheck instance so it can be used to validate stuff right out of the box.

var apiCheck = require('api-check') // note no call ()
apiCheck.warn([apiCheck.object], [apiCheck]) // doesn't work, probably should.

Note the current setup also necessitates creation of two bindings when using module syntax:

import APICheck from 'api-check' // can't import + instantiate on one line
const apiCheck = APICheck() // blegh

Improve messaging

Right now the messaging could be a little bit more clear, especially for shapes (or arrayOf[shape] or objectOf[shape]). If anyone is interested in helping, comment on this issue and we can work on a few test cases to improve messaging. The code around it could use some help as well.

Make the "should have passed" not so hard to understand

This is what it looks like now:

`shape({"name":"String","template":"ifNot[templateUrl] or ifNot[defaultOptions]","templateUrl":"ifNot[template] or ifNot[defaultOptions]","defaultOptions":"","wrapper":"String or arrayOf[String] (optional)","overwriteOk":"Boolean (optional)"}) or arrayOf[shape({"name":"String","template":"ifNot[templateUrl] or ifNot[defaultOptions]","templateUrl":"ifNot[template] or ifNot[defaultOptions]","defaultOptions":"","wrapper":"String or arrayOf[String] (optional)","overwriteOk":"Boolean (optional)"})]`

Just a little crazy. Maybe a newline for the "ors" or something.

Null type

It'd be useful to have a null type. I'm using apiCheck for HTTP response testing (and it's great, thanks ๐Ÿ˜„) and some of my responses can be null.

Here's the custom type I'm using at the moment to work around it:

let nullType = (val, name, location) => {
  if (val !== null) return apiCheck.utils.getError(name, location, 'null')
}

Usage in npm module

Hey there,

I had a question about how best to use api-check when using it in an npm module I'm developing. Currently I'm developing the module as a local module within a larger project, so it is just using the same api-check setup file as is used in the larger application. However, I'd like to soon split this local module out of my project to have it be its own stand-alone npm module.

I would still like to have api-check running for my stand-alone npm module, which I think means I'll need to duplicate the api-check setup file, and instead require it explicitly within the module this time.

I'm wondering if there will be a way to disable api-check for my now npm-required module when building my app in production. I guess the question boils down to: does api-check get disabled if its included in node_modules when building an app in production?

Hope this question makes sense. Thanks a bunch for the excellent package!
Thomas

New Checker: greaterThan, lessThan

This would compliment the range checker.

var checker = apiCheck.greaterThan(2);
checker(4); // <-- passes
checker(1); // <-- fails
var checker = apiCheck.lessThan(6);
checker(4); // <-- passes
checker(10); // <-- fails

Out Of Stack Space error when using IE

I am using this together with Formly and while using a UIB-Autocomplete it triggers an Out of Stack Space error in API-check.

Basically what we are doing is this: We have it set to do an Async Get call where there are more than 2 characters entered in the search box and then that brings back from the Server any matching results. If you type in a bunch of stuff that doesn't match, once you hit 4 or 5 times and then delete back to the beginning to start over, it throws this error on the first character you type in again and crashes.

No issues on Chrome

From what I've read its related to recursion a lot of time and this is apparently a workaround/fix for it:

process.nextTick = (function(){
  var timeouts = []
  // postMessage behaves badly on IE8
  if (window.ActiveXObject || !window.postMessage) {
    return function(fn){
      timeouts.push(fn);
      setTimeout(function(){
        if (timeouts.length) timeouts.shift()();
      }, 0);
    }
  }

  // based on setZeroTimeout by David Baron
  // - http://dbaron.org/log/20100309-faster-timeouts
  var name = 'mocha-zero-timeout'

  window.addEventListener('message', function(e){
    if (e.source == window && e.data == name) {
      if (e.stopPropagation) e.stopPropagation();
      if (timeouts.length) timeouts.shift()();
    }
  }, true);

  return function(fn){
    timeouts.push(fn);
    window.postMessage(name, '*');
  }
})();

Fix is from the mocha project
mochajs/mocha#502

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.