Notoriously Problematic Merge

    snug

    0.3.0 • Public • Published

    Snug

    Build Status

    Make your functions safe at run time. Sometimes your may get data from sources during run time (e.g. the web) where you are not able to take advantage of compile-time type checking. This is for handling checks and pattern matching at run time.

    Install

    npm install snug

    Usage

    Type Annotations

    Make your input and output values snug. The inputs arrays corresponds to the respective input arguments. Functions are expected, so you can add whatever logic you desire for your type. If you do not specify any inputs or outputs, there will be no checks.

    var snug = require('snug');
     
    var sum = snug.annotate({
      inputs: [lodash.isNumber, lodash.isNumber],
      outputs: [lodash.isNumber],
      fn: function(a, b) {
        return a + b;
      }
    });
     
    sum(3, 4); // Returns 7
    sum(3); // TypeError - Not enough arguments
    sum(3, 4, 5); // TypeError - Too many arguments
    sum('a', 'b'); // TypeError - wrong types

    If you would like to define your annotations apart from your functions, simply leave off the fn property. You will then get a function in which you can pass in a function to annotate.

    var snug = require('snug');
     
    var sumAnnotation = snug.annotate({
      inputs: [lodash.isNumber, lodash.isNumber],
      outputs: [lodash.isNumber]
    });
     
    var sum = sumAnnotation(function(a, b) {
      return a + b;
    });
     
    sum(3, '4'); // TypeError

    Catching Errors

    Sometimes, you want to make a function fail gracefully. You can do this with the catch function.

    var snug = require('snug');
     
    var sum = snug.annotate({
      inputs: [lodash.isNumber, lodash.isNumber],
      outputs: [lodash.isNumber],
      fn: function(a, b) {
        return a + b;
      },
      catch: function(error) {
        return 0;
      }
    });
     
    sum('a', 'b'); // TypeError is caught, calls catch function, returns 0

    Creating Prototype Chains

    Sometimes you may want to create prototype chains. The code gets really ugly when doing that and using annotations. Using the create method will let you build a prototype chain that are annotation objects. Note how the fn functions use this.

    var MyFunction = snug.create({
      constructor: {
        fn: function(a) {
          this.a = a;
        }
      },
     
      add: {
        inputs: [lodash.isNumber],
        outputs: [lodash.isNumber],
        fn: function(b) {
          return this.a + b;
        }
      }
    });
     
    var myFn = new MyFunction(1);
    myFn.add(2); // Returns 3

    Pattern Matching

    You can take your annotations and call the first matching function using patternMatch.

    var fib = snug.annotate({
      inputs: [lodash.isNumber],
      fn: snug.patternMatch([
        {
          inputs: [function(n) { return n === 0 || n === 1; }],
          fn: function() { return 1; }
        },
        {
          inputs: [function(n) { return n > 0; }],
          fn: function(n) { return fib(- 2) + fib(- 1); }
        }
      ])
    });
     
    fib(10); // 89
    fib(-10); // Error: No pattern match found
    fib('10'); // TypeError because it requires a number

    You may use .extend to add a catch function for the patternMatch function, which returns an annotation.

    Structures

    You may want to iterate over an object or array to see if every item passes a certain check. There are two functions to help with this.

    Typed Array Structure

    This ensures that every item in the array passes a single test.

    var check = snug.structures.typedArray(lodash.isNumber);
    check([1, 2, 3]); // True
    check([1, '2', 3]); // False

    Compare Array

    You can use this function to compare two arrays.

    var check = snug.structures.compareArray([
      lodash.isNumber,
      lodash.isString,
      lodash.isNumber
    ]);
     
    check([1, '2', 3]); // True
    check([1, 2, 3]); // False

    Object Structure

    This looks at every key in an object and checks to see if each passes the check.

    var check = snug.structures.object({
      foo: lodash.isNumber,
      bar: lodash.isBoolean
    });
     
    check({
      foo: 4,
      bar: true
    }); // True
     
    check({
      foo: 4,
      bar: 'true'
    }); // False
     
    check({
      foo: 4
    }); // False

    Logic

    Sometimes, you need to get fancy with your annotations.

    and

    var check = snug.logic.and([
      lodash.isNumber,
      function(value) { return value < 10; }
    ]);
     
    check(4); // True
    check(100); // False

    or

    var check = snug.logic.or([
      lodash.isNumber,
      function(value) { return value === 'foobar'; }
    ]);
     
    check(4); // True
    check('foobar'); // True
    check('hello world'); // False

    nor

    var check = snug.logic.nor([
      lodash.isNumber,
      function(value) { return value === 'foobar'; }
    ]);
     
    check(9); // False
    check('foobar'); // False
    check('hello world'); // True

    not

    var check = snug.logic.not(lodash.isArray);
     
    check(9); // True
    check([1, 2, 3]); // False

    wildcard

    Maybe you don't care about the type of a given value. If so, you can use wildcard to say any type is fine.

    var check = snug.logic.wildcard();
     
    // No matter what value is given, it will be true
    check('anything'); // True

    optional

    You may have figured out to use the or function with an isUndefined check as the first item to make checks options, but that gets kind of verbose after a while. You can use optional to do a check or pass if the value is undefined.

    var check = snug.logic.optional(lodash.isNumber);
     
    check(4); // True
    check('4'); // False
    check(); // True

    equalLengthWith

    One test is to ensure two arrays are of equal length.

    var check = snug.logic.equalLengthWith([1, 2, 3]);
     
    check([1, 2, 3]); // True
    check([1, 2]); // False

    equals

    Allows for deep testing equality.

    var check = snug.logic.equals([1, 2, 3]);
     
    check([1, 2, 3]); // True
    check([1, 2]); // False

    Access to Config

    Sometimes, when you create an annotation, you may want to access the configuration you passed to it. Each function exposes this through a $config property.

    This is useful for testing annotations.

    var sumAnnotation = snug.annotate({
      inputs: [lodash.isNumber, lodash.isNumber],
      outputs: [lodash.isNumber]
    });
     
    sumAnnotation.$config; // This is the object with inputs and outputs provided above

    Extending Existing Annotations

    If you want an annotation based on an existing annotation, you can use extend.

    // This function does not have a catch function
    var sum = snug.annotate({
      inputs: [lodash.isNumber, lodash.isNumber],
      outputs: [lodash.isNumber],
      fn: function(a, b) {
        return a + b
      }
    });
     
    // This one does, and is a new function
    var sumWithCatch = sum.extend({
      catch: function(error) {}
    });
     
    sum('a'); // Error is not caught
    sumWithCatch('a'); // Error is caught

    Keywords

    none

    Install

    npm i snug

    DownloadsWeekly Downloads

    0

    Version

    0.3.0

    License

    MIT

    Last publish

    Collaborators

    • smizell