API Specification

Standard Library uses an implementation of the open FunctionScript specification to parse function documentation. Standard Library enforces type checking for arguments and return values in accordance with the spec -- we'll show you how you can take advantage of this to create better, more user-friendly APIs here.

Overview

You may have noticed when creating Standard Library services that the default __main__.js function looks something like this:

/**
* A basic Hello World function
* @param {string} name Who you're saying hello to
* @returns {string}
*/
module.exports = (name = 'world', context) => {

  return `hello ${name}`;

};

You'll notice that there are some comments immediately above the actual function declaration. These JSDoc-style comments serve as documentation and allow Standard Library to type check calls to your function. If a call does not supply the correct type for a given parameter, Standard Library will return an error.

This documentation is optional, but it is not possible to document only some parameters or just the return value -- once you start documenting a function, you must document the entire thing. If you do not supply any documentation or default values, Standard Library will not type check your function calls.

Parameters

Declare parameters using @param followed by the type you expect the parameter to be and the name of the parameter as you define it in the function signature. You can also add a description of what the parameter does. In the above example, we declare an argument name that we expect to be a string. Possible types include string, object, buffer, and the any type, which matches every type. For a complete list, see the table below.

Default Values

The name parameter also has a default value, world set. You can specify default values for parameters in the function declaration by writing an equals sign followed by the default value, as shown above. If your function's signature includes a parameter but a caller does not supply it, Standard Library will use the default value for the parameter if it exists, and will otherwise throw an error.

i
If you do not supply documentation but do supply default values for your parameters, Standard Library will attempt to infer the required type of the parameter and will type check calls to your function based on the type of the default value. If you would like to use a default value for a parameter that can be more than one type, document it using the any type.

Return Values

Standard Library type checks return values based on whatever follows @returns in the comments. You should again specify a type following this value or use any if your function can return multiple types.

Allowed Types

Here is a list of all the types you may specify in your documentation:

Type Definition Example Input Values (JSON)
boolean True or False true or false
string Basic text or character strings "hello", "GOODBYE!"
number Any double-precision Floating Point value 2e+100, 1.02, -5
float Alias for number 2e+100, 1.02, -5
integer Subset of number, integers between -2^53 + 1 and +2^53 - 1 (inclusive) 0, -5, 2000
object Any JSON-serializable Object {}, {"a":true}, {"hello":["world"]}
object.http An object representing an HTTP Response. Accepts headers, body and statusCode keys {"body": "Hello World"}, {"statusCode": 404, "body": "not found"}, {"headers": {"Content-Type": "image/png"}, "body": new Buffer(...)}
array Any JSON-serializable Array [], [1, 2, 3], [{"a":true}, null, 5]
buffer Raw binary octet (byte) data representing a file {"_bytes": [8, 255]} or {"_base64": "d2h5IGRpZCB5b3UgcGFyc2UgdGhpcz8/"}
any Any value mentioned above 5, "hello", []
enum An enumeration that maps input strings to values of your choosing "STRING_OF_YOUR_CHOICE"

Type Conversion

The buffer type will automatically be converted from any object with a single key-value pair matching the footprints {"_bytes": []} or {"_base64": ""}.

Otherwise, parameters provided to a function are expected to match their defined types. Requests made over HTTP via query parameters or POST data with type application/x-www-form-urlencoded will be automatically converted from strings to their respective expected types, when possible (see FunctionScript Resource Requests below):

Type Conversion Rule
boolean "t" and "true" become true, "f" and "false" become false, otherwise do not convert
string No conversion
number Determine float value, if NaN do not convert, otherwise convert
float Determine float value, if NaN do not convert, otherwise convert
integer Determine float value, if NaN do not convert, may fail integer type check if not in range
object Parse as JSON, if invalid do not convert, object may fail type check (array, buffer)
object.http Parse as JSON, if invalid do not convert, object may fail type check (array, buffer)
array Parse as JSON, if invalid do not convert, object may fail type check (object, buffer)
buffer Parse as JSON, if invalid do not convert, object may fail type check (object, array)
any No conversion
enum Read input as string

Nullability

All types are potentially nullable, an nullability can be defined in two ways:

(1) by setting "defaultValue": null in the NamedParameter definition.

/**
* @param {string} nullableString
*/
module.exports = (nullableString = null) => {
  return `Test ${nullableString}`;
}

(2) By prepending a ? before the type name in the comment definition, i.e.:

/**
* @param {?string} nullableString
*/
module.exports = (nullableString) => {
  return `Test ${nullableString}`;
}
i
The difference between this two behaviors is that the latter will mean nullableString is both required AND nullable, whereas the former means nullableString has a defaultValue (is optional).

Setting HTTP headers

The object.http type should be used to generate HTTP responses that are intended to return more complex data than simple JSON responses.

You can provide headers, statusCode and body in an object.http response.

For example, to return an image that's of type image/png...

/**
* Retrieves an image
* @param {string} imageName The name of the image
* @returns {object.http} image The result
*/
module.exports = (imageName) => {

  // fetch image, returns a buffer
  let png = imageName === 'cat' ?
    fs.readFileSync(`/images/kitty.png`) :
    fs.readFileSync(`/images/no-image.png`);

  // Forces image/png over HTTP requests, default
  //  for buffer would otherwise be application/octet-stream
  return {
    headers: {'Content-Type': 'image/png'},
    statusCode: 200,
    body: png
  };

};

Further Reading

To learn more about FunctionScript or to contribute, check out the Github repository. The repository includes the open-sourced implementation used by us.