Skip to content

dmikis/bla

 
 

Repository files navigation

bla NPM version Build Status Coverage Status

[ Quick startExamplesBuilt-in API methodsAPI ReferenceContribution guideHeroes]

Provides helpers for writing your own API methods and using them from server and client sides. See also bla-presentation for more details.

The package is versioned according to SemVer.

Features

  • Simple integration.
  • Consistent interface of API methods on the server and client sides.
  • Normalization for request parameters.
  • Automatic documentation generation for all declared API methods.
  • Joining all client requests into one during one tick (see batch method).
  • Enb builder support.

Installation

npm install bla --save

Quick start

Declare API Method

Write API method declaration.

var ApiMethod = require('bla').ApiMethod;

module.exports = new ApiMethod('hello')
    .setDescription('Hello API method')
    .addParam({
        name: 'name',
        description: 'User name',
        required: true
    })
    .setAction(function (params) {
        return 'Hello, ' + params.name;
    });

And save it to api/hello.api.js.

and use it on server side

var Api = require('bla').Api;
var api = new Api(__dirname + '/api/**/*.api.js');
api.exec('hello', {name: 'Stepan'}).then(function (response) {
    console.log(response); // 'Hello, Stepan'
});

or on frontend side

First, include API middleware to your express application.

var app = require('express')();
var bodyParser = require('body-parser');
var apiMiddleware = require('bla').apiMiddleware;
app
    .use(bodyParser.json())
    .use('/api/:method?', apiMiddleware(__dirname + '/api/**/*.api.js'));

Include the client library to .

<script type="text/javascript" src="build/bla.min.js"></script>

or specify bla as enb dependency in package.json.

"enb": {
    "dependencies": [
        "bla"
    ]
}

Then use API module with YM module system

modules.require('bla', function (Api) {
    var api = new Api('/api/');
    api.exec('hello', {name: 'Stepan'}).then(function (response) {
        console.log(response); // 'Hello, Stepan'
    });
});

with require.js

require(['bla'], function (Api) {
    var api = new Api('/api/');
    api.exec('hello', {name: 'Stepan'}).then(function (response) {
        console.log(response); // 'Hello, Stepan'
    });
});

or without module system at all

var api = new bla.Api('/api/');
api.exec('hello', {name: 'Stepan'}).then(function (response) {
    console.log(response); // 'Hello, Stepan'
});

See Api class for more information.

Note. express 4.x is used in all examples. See package.json for more details.

Examples

Use makefile to run an example. For instance,

make run examples/backend/basic_usage.js

Built-in API methods

bla-batch

This method is used on the client side and makes it possible to joint all requests to the server during one tick. It shortens number of request dramatically.

The client side uses this method by default and can be changed with noBatching option of Api class constructor or the noBatching option of the Api.exec method.

Do you want the proves that batch is effective? See bla-benchmark.

API Reference

Class Api

constructor(methodPathPattern)

Creates a new instance of API and collects all your API methods from methodPathPattern path. Path supports minimatch.

Example:

var Api = require('bla').Api;
var api = new Api(__dirname + '/api/**/*.api.js');

exec(methodName, [params], [request])

Executes an API method methodName with the provided params.

An express request can also be passed using request parameter. The middleware proxies it for you.

Returns vow.Promise. Promise will be resolved with a method response or rejected with ApiError.

Example:

api.exec('hello', {name: 'Stepan'})
    .then(function (response) {
        console.log(response);
    })
    .fail(function (error) {
        console.log(error.message);
    });

Class ApiMethod

constructor(methodName)

Creates a new instance of ApiMethod with provided methodName.

ApiMethod class supports chaining for it's methods: setDescription, addParam, and setAction.

Example:

var ApiMethod = require('bla').ApiMethod;
var helloMethod = new ApiMethod('hello');

setDescription(description)

Change method description to provided description.

Example:

helloMethod.setDescription('This is a hello method');

addParam(param)

Add a new param declaration.

API method param is an object with the follow fields:

Name Type Description
name String Parameter name
description String Parameter description
[type] String Parameter type (String, Number, Boolean, etc.)
[required] Boolean Should the parameter be made obligatory

Example:

helloMethod.addParam({
    name: 'name',
    description: 'User name',
    required: true
});

setAction(action)

Sets a function which should be executed when method runs.

Declared parameters will be passed to the action function as a first parameter. If the method is executed via the middleware, expresses request will be passed as a second parameter (undefined for server side execution).

Example:

helloMethod.setAction(function (params, request) {
    return 'Hello, world';
});

A third parameter is an Api instance. It's very useful in cases when the api method executes other api methods.

Example:

method.setAction(function (params, request, api) {
    return api.exec('method1');
});

exec([params], [request])

Executes an API method with provided params.

An express request can also be passed using request parameter. The middleware proxies it for you.

Returns vow.Promise. The promise will be resolved with a method response or rejected with ApiError.

Example:

helloMethod.exec({name: 'Stepan'})
    .then(function (response) {
        console.log(response);
    })
    .fail(function (error) {
        console.log(error.message);
    });

setOption(name, value)

Sets an extra option for the method.

List of available options:

Name Type Description
hiddenOnDocPage Boolean Hides the API method in built documentation.
executeOnServerOnly Boolean Permit to execute method only on server side .

Class ApiError

constructor(type, message)

ApiError is inherited from JavaScript Error class. You can specify type of the error and message with human-readable description of the error.

See bellow supported list of errors.

Example:

var ApiError = require('bla').ApiError;
throw new ApiError(ApiError.INTERNAL_ERROR, 'Internal server error');

Error types

  • ApiError.BAD_REQUEST — Invalid or missed parameter.
  • ApiError.INTERNAL_ERROR — Unspecified error or error in server logic.
  • ApiError.NOT_FOUND — API method or middleware wasn't found.

Express Middleware

var apiMiddleware = require('bla').apiMiddleware(methodPathPattern, options)

The middleware adds a route path for API to your Express application. You need to pass methodPathPattern as you did for Api class or an Api instance itself.

Note. The middleware always proxies an express request to an executed method.

Options

Using the second paremeter options you can tune the middleware up.

Name Type Description
[disableDocPage] Boolean Turn off generating page with documentation. See example.
[buildMethodName] Function express.Request is passed to the function. The function should return a method name. By default methodName is grabbed by executing req.param('method'). See example.

Method parameters are collected from Express request using req.param method.

For example, the apiMiddleware will look for a parameter named myparam in the following order:

  1. In the URL path (/api/:myparam?).
  2. In the request's query string (?myparam=1).
  3. In the request's body.

The middleware accepts GET and POST requests from the client.

Note. Don't forget to add body-parser middleware, because the provided client module uses POST requests.

Also you must specify :method? parameter in the route path used by this middleware or buildMethodName function. Otherwise, the middleware won't find the API method name.

If you don't provide any method name, the middleware will show your the list of all available API methods (special page with documentation). Specified descriptions for methods and params will be used for generating documentation.

Example:

var app = require('express')();
var bodyParser = require('body-parser');
var apiMiddleware = require('bla').apiMiddleware;

app
    .use(bodyParser.json())
    .use('/api/:method?', apiMiddleware(__dirname + '/../api/**/*.api.js'))

You can find a working examples in example/middleware directory.

Response

The middleware returns a response with a JSON string and a 200 status code (even if an error occured). You can distinguish an error and successful response by checking the data and error fields in the root of the response object.

Example of a successful response:

{
    "data": "Hello, Stepan"
}

Example of a response with an error:

{
    "error": {
        "type": "BAD_REQUEST",
        "message": "missing name parameter"
    }
}

Class Api (bla)

Requirements:

  • vow — DOM Promise and Promises/A+ implementation for Node.js and browsers.

constructor(basePath, [options])

Creates a new instance of client API. basePath is used to build the path for AJAX requests to the server. For example, if you define /api as a basePath then all request will be sent to https://<your host>/api/<method name>.

Also you can specify an extra options:

Name Type Description
[noBatching] Boolean|String[] Disable using batch for all client requests (false by default), or if an array of strings is passed, disable batching only for specific methods.

You can use the client-side bundle of bla with different module systems. For example:

// ym
modules.require('bla', function (Api) {
    var api = new Api('/api/');
});

// require.js
require(['bla'], function (Api) {
    var api = new Api('/api/');
});

// without module system
var api = new bla.Api('/api/');

There are two ways for using the noBatching parameter. Disable batching globally:

// all api.exec() calls will NOT be batched
var api = new Api('/api/', {noBatching: true});

Disable batching per method:

// api.exec() calls with method name argument 'slow-poke' will not be batched
var api = new Api('/api/', {noBatching: ['slow-poke']});

exec(methodName, [params], [execOptions])

Sends a request to the server for executing API method with name methodName and provided params. The options argument is used for changing the method behavior. The method returns a vow.Promise.

Name Type Description
[noBatching] Boolean Disable using batch for current request (false by default)

For example:

api.exec('hello')
    .then(function (response) {
        // Be polite! Handle the 'response' properly.
        // ...
    })
    .fail(function (reason) {
        // Even when rejected, a gentleman shouldn't lose his temper. Do something with the 'reason'.
        // ...
    });

If you want to disable the batching for a single api.exec() call:

// method 'slow-poke' won't be batched for this call only
api.exec('slow-poke', {}, {noBatching: true}).then(function () {
    // ...
});

Class ApiError (bla-error)

It works absolutely the same as the server version of ApiError.

Thanks

About

Easy way to create your own API methods for server and client sides

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • JavaScript 99.3%
  • Shell 0.7%