This entry is part 9 of 12 in the series Server-Side JavaScript, Pintura, and Persevere 2.0

CommonJS Utils is a collection of general purpose CommonJS-compliant modules. These modules can be used on Narwhal, Node, and other CommonJS platforms. The modules include:

  • json-schema.js – This is a JSON Schema validator module. It can be used to validate data structures using JSON schema definitions. For example:
    var validate = require("json-schema").validate;
    var data = {name: "Test"};
    var schema = {
      properties: {
         name: {type: "string"},
         age: {type: "number"}
      }
    };
    var validation = validate(data, schema);
    validation.valid -> false
    validation.errors -> indicates that age was not provided
    data.age = 30;
    var validation = validate(data, schema);
    validation.valid -> true
    

    This module also supports using standard native constructors as type definitions. The schema above could be written
    more briefly:

    var schema = {
      properties: {
         name: String,
         age: Number
      }
    };
    
  • json-ext.js – This module provides several JavaScript-valid extensions to a JSON for serialization and parsing of richer data structures. The json-ext.js module supports dates, NaN, Infinity, and undefined using standard JavaScript syntax. For example:
    var JSONExt = require("json-ext");
    var myObj = {now: new Date(), unreals: [NaN, Infinity, -Infinity], notDefined: undefined}
    asString = JSONExt.stringify(myObj);
    // asString -> {now:(new Date(1265260623866)), unreals:[NaN, Infinity, -Infinity], notDefined:undefined}
    myObj = JSONExt.parse(asString);
    
  • observe.js – The observe module event provides listening capabilities that normalize subscribing to events for CommonJS observable objects, Node.js EventEmitters, and plain JavaScript property functions. For those familiar with Dojo, the observe function is the Node/CommonJS equivalent of dojo.connect:
    var observe = require("observe").observe;
    // listen to an "observable" object:
    observe(someObservableObject, "someEvent", function(event){ 
      ... handle event 
    });
    
    // listen to a Node request
    var listener = observe(request, "body", function(data){...});
    
    // we can later stop listening with:
    listener.dismiss();
    
    // plain JavaScript objects can also serve as event sources
    myObj = {
      sayHi: function(){
        print("hi");
      }
    };
    // listen for sayHi to be called
    observe(myObj, "sayHi", function(){
      print("Observed sayHi being called");
    });
    
    myObj.sayHi();
    // this will print out "hi" and then "Observed sayHi being called"
    
  • lazy-array.js – One can utilize lazy array-like structures with the lazy-array module. Normally with standard JavaScript arrays, one needs to populate all the slots in the array before it can utilized by a consumer. However, for scalability of large collections of data, it is often beneficial to only evaluate or load data as needed. This can avoid excessive memory consumption (storing everything in collection at once), and avoid unnecessary evaluations or loading operations if only a subset of a collection is actually used. With the lazy-array module, one can easily implement a lazy array-like collection that is an instanceof Array, and provides all of the functions normally available on Arrays. One simply needs to implement the some() function and provide a length property. For example:
    var LazyArray = require("lazy-array").LazyArray;
    fibonaccis = LazyArray({
      length: 10000000, // effectively Infinity, but that's not a valid array length in JS
      some: function(callback){
        var a = 0, b = 1;
        do{
          var next = a + b; a = b; b = next;
          var done = callback(next);
        }while(!done);
      }
    });
    
    // now we can print the square of first 10:
    var i = 0;
    fibonaccis.map(function(value){
      // lazy-array will use lazy evaluation of the map function, 
      // so we can safely do this without an infinite loop
      return value*value; // compute the square of each
    }).some(function(value){
      if(i++ == 10){ // after 10, signal we are done
        return true;
      }
      print(value);
    });
    

    Lazy arrays are not true arrays in that we can’t use the [index] operator to access items. However, we can grab items by index using the get export from lazy-array:

    var get = require("lazy-array").get;
    get(fibonaccis, 5) -> 13
    

    Furthermore, lazy arrays also support asynchronously evaluated lazy arrays. This effectively becomes a powerful generic data asynchronous streaming mechanism.

    var LazyArray = require("lazy-array").LazyArray;
    var when = require("promise").defer;
    lazyFileParts = LazyArray({
      length: file.size,
      some: function(callback){
        var deferred = defer();
        fileInput.addListener("data", function(data){
          callback(data);
        });
        fileInput.addListener("complete", deferred.resolve);
      }
    });
    // now we can use it
    var defer = require("promise").when;
    when(lazyFileParts.forEach(function(part){
      // called for each part
    }), function(){ 
      // all done
    });
    
  • jsgi-client.js – The jsgi-client module is an HTTP client module that is based on the CommonJS JSGI standard. The JSGI standard was originally developed for HTTP servers, but this module basically follows the same object structure and design, but in reverse. It also provides some alternate options to make it easier to create HTTP requests. This module relies on the browserjs package and Narwhal’s promise module. For example:
    var request = require("jsgi-client").request;
    request({
      uri: "http://example.com/path",
      method: "POST",
      body: '{"foo":"bar"}',
      headers: {
        "Content-Type": "application/json"
      }
    }).then(function(response){
      response.body // -> the response body
      response.headers // -> the response headers
      response.status // -> the response status
    });
    
  • settings.js – The settings module provides access to local configuration information. This configuration information should be stored in a local.json file in your application.
    local.json:
    {
      "database": {
        "connection":"jdbc:mysql://localhost/..."
        "type": "mysql"
      },
     ...
    }
    

    And then we can access this local information:

    var dbConnectionInfo = require("settings").database.connection;
    
  • extend-error.js – The extend-error module provides a means for creating custom error constructors. Creating custom error constructors can be tricky, particularly if you want to preserve the normal error properties with name, message, stack trace information, and standard toString() operations. This module makes it simple:
    var ErrorConstructor = require("extend-error").ErrorConstructor;
    MyCustomError = ErrorConstructor("MyCustomError");
    // now we can use our new error constructor:
    try{
      throw new MyCustomError("error message");
    }
    catch(e){
      print(e); // prints: "MyCustomError: error message"
    }
    
  • smtp.js – This module provides the ability to send email through SMTP. This module requires Rhino. For example:
    var send = require("smpt").send;
    send({
      to: "recipient@example.com",
      subject: "Example",
      message: "This is an example email"
    });
    

    And then your local.json file would need to have the appropriate SMTP settings:

    {
      "mail": {
        "host":"mail.site.com",
        "defaultFrom": "app@site.com"
      }
    }
    
  • xml-rpc.js – The XML RPC module provides basic method invocation through XML RPC. This module is dependent on the browserjs package. For example:
    var XmlRpc = require("xml-rpc").XmlRpc;
    var endPoint = XmlRpc("http://somesite.com/rpc-target");
    var result = endPoint("someMethod", ["arg1", 2]);

The CommonJS utilities package provides these various general purpose utilities. Some of these modules may eventually warrant their own package/project. Any one of these modules can be downloaded from the CommonJS Utils project repository, or you can download the entire CommonJS Utils package.