restful-api-helper v0.0.1
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
statuskey 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-helperUsage
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:
keysare the names of the methods (POST/GET/etc.)valuesare 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
messageanddatakeys. - An object that contains the payload (data). It must not have the keys
messageanddata. - 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 payloadmessage: The user-readable messagestatusCode: 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')orreturn Promise.reject(Error('The error message')).- Calling
res.rSend.failinstead ofres.rSend(same arguments).
I have bundled several other Error objects for your convenience:
HttpError(code, message): The API will respond with amessage, having the HTTP status code ofcode.
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
6 years ago