easy-api

Super easy promise-based api declaration

Usage no npm install needed!

<script type="module">
  import easyApi from 'https://cdn.skypack.dev/easy-api';
</script>

README

logo">

Express wrapper that provides simpler functions to declare API.

Current features

  • Proper promise handling
  • Automatic parameter retrieval
  • Automatic error handling, with custom error capability
  • Simpler static file delivering
  • Simpler file download
  • Simpler cross-site requests enabling

easy-api returns an enhanced version of Express object. Yet nothing is removed. All existing methods remain available.

build status

Install

npm install --save easy-api

Usage

Here are some examples for how you do things using easy-api

Initialization

var easyApi = require('easy-api')

var app = easyApi()

app.getAsync('/music/:musicId', function(musicId) {
    return db.get(musicId)
})

app.getAsync('/music/:musicId/stream', function(musicId) {
    return db.get(musicId).then(function(track) {
        return easyApi.download('audio/mpeg', track.file)
    })
})

app.static('/', './html')

// optional:
// app.enableCrossSiteRequests()

app.start(1337).then(function() {
    console.log('server is running')
})

Route declaration

Every HTTP method is available with the 'Async' suffix, which will provide you the easy-api encapsulation. If you do not want to use easy-api for some route, you can use the classic express methods.

app.getAsync('/message/:id', ...)

app.postAsync('/message/:id', ...)

app.putAsync('/message/:id', ...)

app.deleteAsync('/message/:id', ...)

app.patchAsync('/message/:id', ...)


// or if for some reason (like a feature not yet supported file download for
// instance) you do not wish to use easy-api for a specific route

app.get(...) // classic Express call

Route handler automatic parameter detection

The handler function you pass as parameter will have its parameters automatically fulfilled, with the parameters from the route and also from the body of the request.

app.postAsync('/message/:category', function(category, message) {
    // here you automatically have access to category and message
    //  (message should be a field of the body: see examples below)
})

Route handler Promise handling

Return value

The value returned by the handler is automatically sent in the response as JSON.

app.postAsync('/message/:category', function(category, message) {
    return {id: 42, succes : true}

    // or

    return createMessage(category, message).then(function() {
        return {id: 42, succes : true}
    })
})

When called, this route will set its response headers to 'applcation/json' and send the stringified version of the object, along with a status code of 200

Errors

If an error happens in the handler function, it is automatically caught and a status code 500 is sent, along with the stack of the error. If you want to customize the error, it is possible by .catch()-ing the exception and returning a custom one.

app.getAsync('/message/:id', function(id) {
    return getMessage(id).catch(function(e) {
        e.statusCode = 404
        e.message = 'Could not find message with id: ' + id
        throw e
    })
})

Delivring static content

If you want to deliver some static content, a function is available to do so:

app.static('/', './static/')

Allowing cross-site requests

If you want to enable requests from cross-sites origins, all you have to do is:

// this should be done before declaring any route
app.enableCrossSiteRequests()

Examples

You can browse to the examples folder of the project in order to check out some usage examples.

Features in progress

  • File upload
  • Automatic client generation
  • REST model declaration

Client-side (code snippets for convenience)

Using request (or request-promise)
request.get({
    url : '/message/1',
    json : true
})

request.post({
    uri: '/message/catSound',
    json : true,
    body : {
        message : 'Meow'
    }
})
Using XMLHttpRequest
request('GET', '/message/1')
request('POST', '/message/catSound', {
    message : 'meow'
})

function request(type, url, content) {
    return new Promise(function(resolve, reject) {
        var req = new XMLHttpRequest()
        req.open(type.toUpperCase(), url, true)
        var params = JSON.stringify(content)

        req.setRequestHeader("Content-type", "application/json")
        req.setRequestHeader("Content-length", params.length)
        req.setRequestHeader("Connection", "close")

        req.onreadystatechange = function(aEvt) {
            if (req.readyState == 4) {
                if (req.status == 200)
                    resolve(JSON.parse(req.responseText))
                else
                    reject()
            }
        }
        req.send(params)
    })
}

Tests

Code is thoroughly tested and has been written using TDD.

npm test

build status Please open issues in GitHub if you encounter any problem using this module.

Star the project if you like it :)

Thanks