0.0.1 • Published 5 years ago

restful-api-helper v0.0.1

Weekly downloads
4
License
MIT
Repository
github
Last release
5 years ago

restful-api-helper

Small utilities that help writing consistent and controlled API endpoints more easily.

The idea

restful-api-helper helps you write better API, which I explored in this blog post. Subjectively, a good API has several key ideas:

  • Consistency
  • Has a status key to inform if the request is successful or not.
  • Envelope data. No API response data (payload) should be in the root.
  • Provide a user-readable message in the key message.

Obviously, this is a matter of debate. Therefore, restful-api-helper will allow you to customize this in a future version. For now, an API response will have the following format:

{
  "status": "ok / error",
  "message": "a user-readable message",
  "data": "<payload object>"
}

Installation

npm install restful-api-helper

Usage

restful-api-helper supports any frameworks that have the signature (req, res). This includes Node.js HTTP Server, express.js, Next.js API Routes, etc.

Get started by importing the package:

api = require('restful-api-helper');

api(req, res, handlerObject)

req and res correspond to those in Node.js HTTP Server, express.js or Next.js API Routes.

handlerObject defines how each method is handled. It is an object in which:

  • keys are the names of the methods (POST/GET/etc.)
  • values are functions that handle the corresponding methods
{
  POST: theFunctionToHandlePostRequest
  GET: theFunctionToHandleGetRequest
  ...otherMethods
}

The handle functions

A function to handle POST/GET/etc. request can either be synchronous or asynchronous (like Promise).

There are two ways to returns data and message.

Return the message and payload

The function may returns:

  • An object contains both or either message and data keys.
  • An object that contains the payload (data). It must not have the keys message and data.
  • A string which will be parsed as the message (in case there is no payload)

res.rSend(data, message, statusCode, headers)

Instead of returning a value, you may call res.rSend() with:

  • data: The payload
  • message: The user-readable message
  • statusCode: The HTTP Status Code to set when response.
  • headers: An object - The headers to set when response.

You do not need to call return as res.rSend() will stop the execution immediately (The code after res.rSend will not be executed).

Failed request

You can make the request a failure (incorrect password, permission error, etc.) at any time by:

  • throw new Error('The error message') or return Promise.reject(Error('The error message')).
  • Calling res.rSend.fail instead of res.rSend (same arguments).

I have bundled several other Error objects for your convenience:

  • HttpError(code, message): The API will respond with a message, having the HTTP status code of code.

Example

//  Using commonjs
const api = require('restful-api-helper');
const { HttpError } = require('restful-api-helper');
//  OR: Using ES6 Import
import api, { HttpError } from 'restful-api-helper';

const handler = (req, res) =>
  api(req, res, {
    GET: () => {
      //  Define the function to handle GET request
      const postData = getPost(req.query.postId);
      //  Return the payload and a message
      return {
        data: postData,
        message: `Fetched post with Id ${req.query.postId} successfully`,
      };
      //  OR: Return just the payload
      return postData;
      //  OR: Return just a message
      return `Fetched post with Id ${req.query.postId} successfully... but I do not have the postData because this is just a message`;
    },
    PATCH: () => {
      if (!isAuthenticated) {
        throw new HttpError(401, 'You must be authenticated to update a post');
        //  OR
        return Promise.reject(
          HttpError(401, 'You must be authenticated to update a post')
        );
        //  OR
        res.rSend.fail(null, 'You must be authenticated to update a post', 401);
      }
      if (!req.body.postData) {
        //  you can throw a generic Error()
        throw new Error('You need to write something to update a post');
      }
      //  Let's say our updatePost function returns a promise
      return updatePost(req.body.postId, req.body.postData).then(
        () => 'Post updated!'
      );
      //  You do not have to (and should not) catch the failed promise because it will be handled by restful-api-helper
    },
  });

//  Usage in express.js
app.all('/api/posts', handler);
//  Usage in Next.js (in pages/api/posts.js)
export default handler;
//  usage it in node.js HTTP Server
const server = http.createServer((req, res) => {
  //  oh boy, no native routing solution...
  if (req.url === '/api/posts') return handler(req, res);
});

Contributing

Please see my contributing.md.

License

MIT