api-utils

The api-utils module provides some helpers useful to the SDK's high-level API implementations.

Introduction

The SDK high-level API design guidelines make a number of recommendations. This module implements some of those patterns so that your own implementations don't need to reinvent them.

For example, public constructors should be callable both with and without the new keyword. Your module can implement this recommendation using the publicConstructor function.

Options objects or "dictionaries" are also common throughout the high-level APIs. The guidelines recommend that public constructors should generally define a single options parameter rather than defining many parameters. Since one of the SDK's principles is to be friendly to developers, ideally all properties on options dictionaries should be checked for correct type, and informative error messages should be generated when clients make mistakes. With the validateOptions function, your module can easily do so.

And objects are sometimes iterable over a custom set of key/value pairs. Such objects should have custom iterators that let consumers iterate keys, values, or [key, value] pairs. The addIterator function makes it easy to do so in a way that is consistent with the behavior of default iterators during for...in, for each...in, and for...in Iterator() loops.

API Reference

Functions

publicConstructor(privateConstructor)

Returns a function C that creates an instance of privateConstructor. C may be called with or without the new keyword.

The prototype of each instance returned from C is C.prototype, and C.prototype is an object whose prototype is privateConstructor.prototype. Instances returned from C are therefore instances of both C and privateConstructor.

Additionally, the constructor of each instance returned from C is C.

Instances returned from C are automatically memory tracked using memory.track under the bin name privateConstructor.name.

Example

function MyObject() {}
exports.MyObject = apiUtils.publicConstructor(MyObject);
privateConstructor : constructor
Returns: function

A function that makes new instances of privateConstructor.

validateOptions(options, requirements)

A function to validate an options dictionary according to the specified constraints.

map, is, and ok are used in that order.

The return value is an object whose keys are those keys in requirements that are also in options and whose values are the corresponding return values of map or the corresponding values in options. Note that any keys not shared by both requirements and options are not in the returned object.

Examples

A typical use:

var opts = { foo: 1337 };
var requirements = {
  foo: {
    map: function (val) val.toString(),
    is: ["string"],
    ok: function (val) val.length > 0,
    msg: "foo must be a non-empty string."
  }
};
var validatedOpts = apiUtils.validateOptions(opts, requirements);
// validatedOpts == { foo: "1337" }

If the key foo is optional and doesn't need to be mapped:

var opts = { foo: 1337 };
var validatedOpts = apiUtils.validateOptions(opts, { foo: {} });
// validatedOpts == { foo: 1337 }

opts = {};
validatedOpts = apiUtils.validateOptions(opts, { foo: {} });
// validatedOpts == {}
options : object

The options dictionary to validate. It's not modified. If it's null or otherwise falsey, an empty object is assumed.

requirements : object

An object whose keys are the expected keys in options. Any key in options that is not present in requirements is ignored. Each value in requirements is itself an object describing the requirements of its key. The keys of that object are the following, and each is optional:

[ map : function ]

A function that's passed the value of the key in the options. map's return value is taken as the key's value in the final validated options, is, and ok. If map throws an exception it is caught and discarded, and the key's value is its value in options.

[ is : array ]

An array containing the number of typeof type names. If the key's value is none of these types it fails validation. Arrays and nulls are identified by the special type names "array" and "null"; "object" will not match either. No type coercion is done.

[ ok : function ]

A function that is passed the key's value. If it returns false, the value fails validation.

[ msg : string ]

If the key's value fails validation, an exception is thrown. This string will be used as its message. If undefined, a generic message is used, unless is is defined, in which case the message will state that the value needs to be one of the given types.

Returns: object

A validated options dictionary given some requirements. If any of the requirements are not met, an exception is thrown.

addIterator(obj, keysValsGen)

Adds an iterator to the specified object that iterates keys, values, or [key, value] pairs depending on how it is invoked, i.e.:

for      (var key in obj)                  { ... } // iterate keys
for each (var val in obj)                  { ... } // iterate values
for      (var [key, val] in Iterator(obj)) { ... } // iterate pairs

If your object only iterates either keys or values, you don't need this function. Simply assign a generator function that iterates the keys/values to your object's __iterator__ property instead, f.e.:

obj.__iterator__ = function () { for each (var i in items) yield i; }
obj : object

the object to which to add the iterator

keysValsGen : function

a generator function that yields [key, value] pairs