JavaScript Code Contract Libraries?

后端 未结 4 790
花落未央
花落未央 2021-02-01 08:11

I am just starting up a new web application and I want to implement some form of contract\'esque style validation in my JavaScript. I did some quick googling, and came across Js

相关标签:
4条回答
  • 2021-02-01 08:54

    I may suggest you the next code contracts library: dbc-code-contracts.


    NPM: https://www.npmjs.com/package/dbc-code-contracts

    GitLab repo (home): https://gitlab.com/o.oleg/orbios.dbc#README

    CI-builds with the unit-tests: https://gitlab.com/o.oleg/orbios.dbc/-/jobs/


    Sample code:

    Dbc.Contract.throwException = true;
    
    const domId = "my-div";
    const div   = document.createElement("div");
    div.id .    = domId;
    document.body.appendChild(div);
    
    const state = Dbc.Dom.removeById(domId);
    Dbc.Contract.isTrue(state);
    Dbc.Contract.isNull(document.getElementById(domId));
    

    The following contracts are supported (2nd November, 2017):

    1. isFunction
    2. isObject
    3. isSymbol
    4. isBoolean
    5. isTrue
    6. isFalse
    7. isString
    8. isEmptyString
    9. isNotEmptyString
    10. areStringsEqual
    11. isNumber
    12. isNumberLess
    13. isNumberBigger
    14. areNumbersEqual
    15. isValueNaN
    16. isDefined
    17. isUndefined
    18. isNull
    19. isArray
    20. isEmptyArray
    21. isNotEmptyArray
    22. isObjectImmutable
    23. isPromise
    24. isPrototypeOf

    Also, there are internal contract checks, inside the DOM methods from this library.

    0 讨论(0)
  • 2021-02-01 08:56

    I also have thrown together my idea of type contracts, which does what I want. A little late, I think, but I'll recommend it nevertheless for people willing to look at it: https://github.com/lindem/FirstContract

    It's a WIP, but I needed something like it.

    function bmi (weight, height) {
        return weight / height * height;
    }
    
    var c = require("firstcontract").c
        /* 
         * contract applies to function taking two non-negative numbers,
         * returning a negative number: 
         */
        , contract = c(["R+0", "R+0"], "R+0")
        , cbmi = contract(bmi)
        ;
    

    it was created so that I can add and remove it without changing the function monitored itself and provides just a clamp around the function. It's commonjs and on npm.

    0 讨论(0)
  • 2021-02-01 08:58

    One more - https://www.npmjs.com/package/bycontract It's a small library that expects JSDoc expressions (http://usejsdoc.org/) for a contract. A good chance for you are already familiar with the syntax.

    Just see it in action:

    // Simple test
    byContract( true, "boolean" ); // ok
    // Multiple Types
    byContract( 100, "string|number|boolean" ); // ok 
    // Optional Parameters
    function foo( bar, baz ) {
      byContract( arguments, [ "number=", "string=" ] );
    }
    

    Here kinda real-world example:

    /**
     * @param {number|string} sum
     * @param {Object.<string, string>} payload
     * @param {function} cb
     * @returns {HTMLElement}
     */
    function foo( sum, payload, cb ) {
      // Test if the contract is respected at entry point 
      byContract( arguments, [ "number|string", "Object.<string, string>", "function" ] );
      // .. 
      var res = document.createElement( "div" );
      // Test if the contract is respected at exit point 
      return byContract( res, HTMLElement );
    }
    // Test it 
    foo( 100, { foo: "foo" }, function(){}); // ok 
    foo( 100, { foo: 100 }, function(){}); // exception - ByContractError: Value of index 1 violates the contract `Object.<string, string>` 
    
    0 讨论(0)
  • 2021-02-01 09:06

    Given that no one has recommended any existing libraries, or that I am crazy for thinking this is a good idea I went ahead and threw together a basic library. The code isn't fancy, but it does what I want, and it is reasonably fast to run (approx 40 chained checks per ms in IE).

    I settled on a final syntax like:

    function syncTime(serverTime, now) {
      Verify.value(serverTime).always().isDate();   // Cannot be undefined or null.
      Verify.value(now).whenDefined().isDate();     // Cannot be null, but must be date when defined.
    
      //Code
    }
    
    function searchForUser(firstName, middleInit, lastName) {
      Verify.value(firstName).always().isString().withMinimumLengthOf(2);  // Cannot be undefined or null.
      Verify.value(lastName).always().isString().withMinimumLengthOf(2);   // Cannot be undefined or null.
      Verify.value(middleInit).whenNotNull().isChar().between('A', 'Z');   // Cannot be undefined, but must be single char string when not null.
    
      //Code
    }
    

    I opted for an explicit 'Must Have Value' via the .always() check, personally I found it nicer to read; but I could see some going another way.

    Given that the source is more than I want to post in this answer, please head to this CodePlex Wiki Page if you are interested in the source. I guess it turned in to more of a fluent assertion library; but it does what I need.

    Update

    I updated the source on the linked CodePlex page above. Specifically, I restructed the Verify class to make use of a 'value context' rather than always building new Verifier objects; improved IE's performance greatly (never was an issue with FireFox or Chrome)... now handles about 100 chained checks per ms in IE.

    0 讨论(0)
提交回复
热议问题