Code Monkey home page Code Monkey logo

aproba's Introduction

aproba

A ridiculously light-weight function argument validator

var validate = require("aproba")

function myfunc(a, b, c) {
  // `a` must be a string, `b` a number, `c` a function
  validate('SNF', arguments) // [a,b,c] is also valid
}

myfunc('test', 23, function () {}) // ok
myfunc(123, 23, function () {}) // type error
myfunc('test', 23) // missing arg error
myfunc('test', 23, function () {}, true) // too many args error

Valid types are:

type description
* matches any type
A Array.isArray OR an arguments object
S typeof == string
N typeof == number
F typeof == function
O typeof == object and not type A and not type E
B typeof == boolean
E instanceof Error OR null (special: see below)
Z == null

Validation failures throw one of three exception types, distinguished by a code property of EMISSINGARG, EINVALIDTYPE or ETOOMANYARGS.

If you pass in an invalid type then it will throw with a code of EUNKNOWNTYPE.

If an error argument is found and is not null then the remaining arguments are optional. That is, if you say ESO then that's like using a non-magical E in: E|ESO|ZSO.

But I have optional arguments?!

You can provide more than one signature by separating them with pipes |. If any signature matches the arguments then they'll be considered valid.

So for example, say you wanted to write a signature for fs.createWriteStream. The docs for it describe it thusly:

fs.createWriteStream(path[, options])

This would be a signature of SO|S. That is, a string and and object, or just a string.

Now, if you read the full fs docs, you'll see that actually path can ALSO be a buffer. And options can be a string, that is:

path <String> | <Buffer>
options <String> | <Object>

To reproduce this you have to fully enumerate all of the possible combinations and that implies a signature of SO|SS|OO|OS|S|O. The awkwardness is a feature: It reminds you of the complexity you're adding to your API when you do this sort of thing.

Browser support

This has no dependencies and should work in browsers, though you'll have noisier stack traces.

Why this exists

I wanted a very simple argument validator. It needed to do two things:

  1. Be more concise and easier to use than assertions

  2. Not encourage an infinite bikeshed of DSLs

This is why types are specified by a single character and there's no such thing as an optional argument.

This is not intended to validate user data. This is specifically about asserting the interface of your functions.

If you need greater validation, I encourage you to write them by hand or look elsewhere.

aproba's People

Contributors

evocateur avatar genisysram avatar iarna avatar mikesherov avatar terriko avatar wouldgo 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

aproba's Issues

Ambiguous error message: "Expected object but got object" when passing an array

I got this error when accidentally passing an array in package.json.

It happens because the "but got..." uses typeof value, which returns "object" for arrays.
Maybe instead of using "typeof" for the error message, using Object.prototype.toString.call(value) would be better? or something else which would distinguish an array from an object..

Sounds like a small problem but it took me a while to find my package.json error, due to the unclear error message.

aproba-overload

Hey,

I found your package tracing makara and adaro a couple months back and I found it really useful in a project I am now working on, so THANK YOU 👍 !

That said, I found my project to benefit from having a T/F returned for use in cases of function overloading via optional params.

TL;DR: I wrote a wrapper function which adds OR(|) and returns T/F if meets or doesn't meet schema. Do you want it? I'll make a PR.

My use case if a router function takes in multiple configurations.

  • function (options, [callback]) {}
  • function (template, dataObj, [options], [callback]) {}

After taking the information in, I parse into a single options object and call an internal function to do the actual work.

var q = require('q');
var extend = require('deep-extend');
var probe = require('./aproba-overload');

module.exports = {
  _compileOptions: {
    engine: null,
    template: null,
    data: null
  },
  _compile: function (options, callback) {
    var d = q.defer();

    // Do compile and resolve/reject promise

    return d.promise.nodeify(callback);
  },

  /**
   * Compile template
   * 
   * @param {String|Object} template   Either template name or options object
   * @param {Object}        [data]     data for template rendering
   * @param {Object}        [options]  optional object for options
   * @param {Function}      [callback] optional callback, returns promise of null
   * 
   * @return {q.Promise|null} promise if no callback, null if returned.
   */
  compile: function (template, data, options, callback) {
    var args = arguments;
    var opts = extend({}, module.exports._compileOptions);


    if (probe('O|OF', args)) { // Options with optional callback
      extend(opts, args[0]);
      callback = args[1];
    } else if (probe('SO|SOF', args)) { // template name and data, optional callback
      opts.template = args[0];
      opts.data = args[1];
      callback = args[2];
    } else if (probe('SOO|SOOF', args)) { // template name and data, additional template options, optional callback
      extend(opts, args[2]);
      opts.template = args[0];
      opts.data = args[1];
      callback = args[3];
    } else {
      throw new Error('Invalid Arguments'); // need more descriptive error message.
    }

    return module.exports._compile(opts, callback);
  }
};

Here is my wrapper:

/**
 * Filename: aproba-overload.js
 * Created by rhett on 2/22/16.
 */
'use strict';
var aproba = require('aproba');

var validate = module.exports = function (schema, args, throwErr) {

  // Enable OR syntax
  if (/.+\|.+/.test(schema)) {  // example schema = 'O|OF|O*F'
    var t = schema.split(/\|(.+)/); // t = ['O', 'OF|O*F', '']

    // return recursive for schema = 'O' OR recursive for schema = 'OF|O*F' <= which has another recurse
    return validate(t[0], args, throwErr) || validate(t[1], args, throwErr);
    // Todo: problem with throwErr here; If true passed it may not reach second call. Rethink this combo
  }

  try {
    aproba(schema, args);
  } catch (err) {
    if (!throwErr &&      // pass-through requested
      [
        'EMISSINGARG',
        'EUNKNOWNTYPE',
        'EINVALIDTYPE',
        'ETOOMANYARGS'
      ].indexOf(err.code) // Catch only known errors
    ) {
      return false;       // Doesn't meet schema
    } else {
      throw err;          // pass-through or other, unexpected error
    }
  }

  return true; // no problems, success
};

At the moment it is just a file in my libs, but I plan to later make into a tested module. Alternatively, I can make a pull request to add this into aproba if you are interested in having it.

If you think this code will be beneficial to you code base, tell me how you think it would be best to add. Otherwise, I'll just make a new package.

Have a great day,

SyntaxError: Invalid or unexpected token

Every time I want to use npm this error appears on Windows 10.
Cannot do anything, even reinstall nodejs several times, I tried node v8 and v10 and older versions.
What can I do ? I'm stuck.

C:\Users\tymme\AppData\Roaming\npm\node_modules\npm\node_modules\aproba\index.js:1
(function (exports, require, module, __filename, __dirname) { +�I��B�♦9A��☻s-H�§�U☺
                                                               ^

SyntaxError: Invalid or unexpected token
    at new Script (vm.js:74:7)
    at createScript (vm.js:246:10)
    at Object.runInThisContext (vm.js:298:10)
    at Module._compile (internal/modules/cjs/loader.js:657:28)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:700:10)
    at Module.load (internal/modules/cjs/loader.js:599:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:538:12)
    at Function.Module._load (internal/modules/cjs/loader.js:530:3)
    at Module.require (internal/modules/cjs/loader.js:637:17)
    at require (internal/modules/cjs/helpers.js:20:18)

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.