diff --git a/README.md b/README.md index a53abf4..e0709cc 100644 --- a/README.md +++ b/README.md @@ -19,13 +19,13 @@ ## Using -The http-handler-response provides two main functions. `makeErr` and `makeRes`. +The http-handler-response provides two main functions. `createError` and `createResponse`. -#### makeErr +### createError -The `makeErr` function is the function responsible for formulating your return messages in unsuccessful requests. It follows the [RFC-7807](https://tools.ietf.org/html/rfc7807) standard. +The `createError` function is the function responsible for formulating your return messages in unsuccessful requests. It follows the [RFC-7807](https://tools.ietf.org/html/rfc7807) standard. -##### Parameters +#### Parameters ```js code: number @@ -35,10 +35,10 @@ The `makeErr` function is the function responsible for formulating your return m instance: string, ``` -##### Example +#### Example ```js -import { makeErr } from 'http-handler-response' +import { createError, handlerErrorAdonis } from 'http-handler-response' import User from 'models/User' class UserController { @@ -47,7 +47,7 @@ class UserController { const user = await User.find(1) if (!user) - makeErr({ + createError({ code: 404, detail: 'The user informed is not registered.', instance: '/user/1', @@ -56,13 +56,13 @@ class UserController { return user } catch (error) { - response.status(error.status).send(error) + handlerErrorAdonis({ response, error }) } } } ``` -##### Response +#### Response ```js { @@ -75,11 +75,11 @@ class UserController { ``` -#### makeRes +### createResponse -The `makeRes` function is the function responsible for formulating your return messages in successful requisitions. +The `createResponse` function is the function responsible for formulating your return messages in successful requisitions. -##### Parameters +#### Parameters ```js code: number, @@ -88,10 +88,10 @@ The `makeRes` function is the function responsible for formulating your return m data: array | object ``` -##### Example +#### Example ```js -import { makeRes } from 'http-handler-response' +import { createResponse, handlerErrorAdonis } from 'http-handler-response' import User from 'models/User' class UserController { @@ -105,20 +105,20 @@ class UserController { await user.save() return response.status(201).send( - makeRes({ + createResponse({ code: 201, message: 'Successful registered user.', data: user, }), ) } catch (error) { - response.status(error.status).send(error) + handlerErrorAdonis({ response, error }) } } } ``` -##### Response +#### Response ```js { @@ -133,3 +133,49 @@ class UserController { } ``` + +### handlerError + +The http-handler-response has custom handlers for handling errors for various web frameworks such as `AdonisJs`, `Express` and `KoaJs`. The functions have a default prefix `handlerError` followed by the name of the framework . Ex: `handlerErrorExpress`. + +#### Parameters + +Some parameters vary in nomenclature, depending on the framework. The idea is to avoid desessentiary statements like `{ response: res }` to simply `{ res }`. + +##### AdonisJs + +```js + response: Response, + error: Error, +``` + +##### Express + +```js + res: Response, + error: Error, +``` + +##### KoaJs + +```js + ctx: Context, + error: Error, +``` + +#### Example + +```js +import { handlerErrorAdonis } from 'http-handler-response' +import User from 'models/User' + +class UserController { + async store(request, response) { + try { + // Your code.. + } catch (error) { + handlerErrorAdonis({ response, error }) + } + } +} +``` diff --git a/__tests__/makeErr.spec.ts b/__tests__/createError.spec.ts similarity index 86% rename from __tests__/makeErr.spec.ts rename to __tests__/createError.spec.ts index d34b0d5..d21e2e8 100644 --- a/__tests__/makeErr.spec.ts +++ b/__tests__/createError.spec.ts @@ -1,8 +1,8 @@ -import makeErr from '../lib/makeErr' +import createError from '../lib/builders/createError' -describe('Make error', () => { +describe('Create error', () => { it('Must return a 401 error for a failed login attempt.', () => { - const error = makeErr({ + const error = createError({ code: '401', detail: 'Informed credentials are invalidated.', instance: '/auth/user', @@ -19,7 +19,7 @@ describe('Make error', () => { }) it('You must mount an error message with a custom title.', () => { - const error = makeErr({ + const error = createError({ code: '401', title: 'Credentials invalid', detail: 'Informed credentials are invalidated.', diff --git a/__tests__/makeModelMessage.spec.ts b/__tests__/createModelMessage.spec.ts similarity index 65% rename from __tests__/makeModelMessage.spec.ts rename to __tests__/createModelMessage.spec.ts index 2832a65..6d29a06 100644 --- a/__tests__/makeModelMessage.spec.ts +++ b/__tests__/createModelMessage.spec.ts @@ -1,14 +1,14 @@ -import makeModelMessage from '../lib/makeModelMessage' +import createModelMessage from '../lib/builders/createModelMessage' -describe('Make message model', () => { +describe('Create message model', () => { it('Must mount a base header with status 500 and title Internal Server Error', () => { - const model = makeModelMessage({ code: '500' }) + const model = createModelMessage({ code: '500' }) expect(model).toEqual({ status: 500, title: 'Internal Server Error' }) }) it('Must mount a custom headline for a 500 error.', () => { - const model = makeModelMessage({ + const model = createModelMessage({ code: '500', title: 'Server found a problem', }) diff --git a/__tests__/makeRes.spec.ts b/__tests__/createResponse.spec.ts similarity index 82% rename from __tests__/makeRes.spec.ts rename to __tests__/createResponse.spec.ts index b82cfd7..5487f31 100644 --- a/__tests__/makeRes.spec.ts +++ b/__tests__/createResponse.spec.ts @@ -1,8 +1,8 @@ -import makeRes from '../lib/makeRes' +import createResponse from '../lib/builders/createResponse' -describe('Make response', () => { +describe('Create response', () => { it('Must mount a successful response with status code 201', () => { - const response = makeRes({ + const response = createResponse({ code: '201', message: 'Successfully registered', data: { @@ -23,7 +23,7 @@ describe('Make response', () => { }) it('You must assemble a response with a personalized title', () => { - const response = makeRes({ + const response = createResponse({ code: '201', title: 'Success', message: 'Successfully registered', diff --git a/lib/makeErr.ts b/lib/builders/createError.ts similarity index 69% rename from lib/makeErr.ts rename to lib/builders/createError.ts index 4a53967..db8336c 100644 --- a/lib/makeErr.ts +++ b/lib/builders/createError.ts @@ -1,8 +1,8 @@ -import { IMakeErr, IError } from './types' -import makeModelMessage from './makeModelMessage' +import { ICreateError, IError } from '../types/builders' +import makeModelMessage from './createModelMessage' /** - * @function makeErr + * @function createError * * Creates an error response following the RFC 7807 pattern. * @@ -12,13 +12,13 @@ import makeModelMessage from './makeModelMessage' * @param instance - URI exclusive for or specific error * @param title - Short and descriptive information */ -const makeErr = ({ +const createError = ({ code, type = 'about:blank', title, detail, instance, -}: IMakeErr): IError => +}: ICreateError): IError => Object.assign(makeModelMessage({ code, title }), { type, detail, instance }) -export default makeErr +export default createError diff --git a/lib/makeModelMessage.ts b/lib/builders/createModelMessage.ts similarity index 52% rename from lib/makeModelMessage.ts rename to lib/builders/createModelMessage.ts index 6b04354..085cfb7 100644 --- a/lib/makeModelMessage.ts +++ b/lib/builders/createModelMessage.ts @@ -4,41 +4,41 @@ import { REDIRECTION, CLIENT_ERROR, SERVER_ERROR, -} from './httpCodes' +} from '../utils/httpCodes' import { - IMakeMessage, + ICreateModelMessage, TInformational, TSuccess, TRedirection, TClientError, TServerError, -} from './types' +} from '../types/builders' /** - * @function makeModelMessage + * @function createModelMessage * * Assemble the default message header. * * @param code - HTTP status code 1xx to 5xx * @param title - Short and descriptive information */ -const makeModelMessage = ({ code, title }: IMakeMessage) => { +const createModelMessage = ({ code, title }: ICreateModelMessage) => { const _code = Number(code) var _title if (_code >= 100 && _code < 200) { - _title = title ?? INFORMATIONAL[code as TInformational] + _title = INFORMATIONAL[code as TInformational] } else if (_code >= 200 && _code < 300) { - _title = title ?? SUCCESS[code as TSuccess] + _title = SUCCESS[code as TSuccess] } else if (_code >= 300 && _code < 400) { - _title = title ?? REDIRECTION[code as TRedirection] + _title = REDIRECTION[code as TRedirection] } else if (_code >= 400 && _code < 500) { - _title = title ?? CLIENT_ERROR[code as TClientError] + _title = CLIENT_ERROR[code as TClientError] } else { - _title = title ?? SERVER_ERROR[code as TServerError] + _title = SERVER_ERROR[code as TServerError] } - return { title: _title, status: _code } + return { title: title ?? _title, status: _code } } -export default makeModelMessage +export default createModelMessage diff --git a/lib/builders/createResponse.ts b/lib/builders/createResponse.ts new file mode 100644 index 0000000..d91b3f9 --- /dev/null +++ b/lib/builders/createResponse.ts @@ -0,0 +1,22 @@ +import { ICreateResponse, IResponse } from '../types/builders' +import createModelMessage from './createModelMessage' + +/** + * @function createResponse + * + * Simple model for successful responses. + * + * @param code - HTTP status code 1xx to 3xx + * @param message - Legible action response + * @param data - Back Data + * @param title - Short and descriptive information + */ +const createResponse = ({ + code, + data, + message, + title, +}: ICreateResponse): IResponse => + Object.assign(createModelMessage({ code, title }), { data, message }) + +export default createResponse diff --git a/lib/builders/index.ts b/lib/builders/index.ts new file mode 100644 index 0000000..46ce158 --- /dev/null +++ b/lib/builders/index.ts @@ -0,0 +1,2 @@ +export { default as createResponse } from './createResponse' +export { default as createError } from './createError' diff --git a/lib/handlers/defaultError.ts b/lib/handlers/defaultError.ts new file mode 100644 index 0000000..0bd98f4 --- /dev/null +++ b/lib/handlers/defaultError.ts @@ -0,0 +1,13 @@ +import createError from '../builders/createError' +import { IError } from '../types/builders' + +/** + * Default Server error + */ + +const defaultError: IError = createError({ + code: '500', + detail: 'There was an internal server error.', +}) + +export default defaultError diff --git a/lib/handlers/handlerErrorAdonis.ts b/lib/handlers/handlerErrorAdonis.ts new file mode 100644 index 0000000..311a749 --- /dev/null +++ b/lib/handlers/handlerErrorAdonis.ts @@ -0,0 +1,17 @@ +import { IAdonisErrorHandler } from '../types/handlers' +import defaultError from './defaultError' + +/** + * @function handlerErrorAdonis + * + * Adonis Error handler + * + * @param response - Adonis response object instance + * @param error - Error object instance + */ +const handlerErrorAdonis = ({ response, error }: IAdonisErrorHandler) => { + error = error?.status ? error : defaultError + return response.status(error.status).json(error) +} + +export default handlerErrorAdonis diff --git a/lib/handlers/handlerErrorExpress.ts b/lib/handlers/handlerErrorExpress.ts new file mode 100644 index 0000000..55f8358 --- /dev/null +++ b/lib/handlers/handlerErrorExpress.ts @@ -0,0 +1,17 @@ +import { IExpressErrorHandler } from '../types/handlers' +import defaultError from './defaultError' + +/** + * @function handlerErrorExpress + * + * Express Error handler + * + * @param res - Express response object instance + * @param error - Error object instance + */ +const handlerErrorExpress = ({ res, error }: IExpressErrorHandler) => { + error = error?.status ? error : defaultError + return res.status(error.status).json(error) +} + +export default handlerErrorExpress diff --git a/lib/handlers/handlerErrorKoa.ts b/lib/handlers/handlerErrorKoa.ts new file mode 100644 index 0000000..d73fcc8 --- /dev/null +++ b/lib/handlers/handlerErrorKoa.ts @@ -0,0 +1,21 @@ +import { IKoaErrorHandler } from '../types/handlers' +import defaultError from './defaultError' + +/** + * @function handlerErrorKoa + * + * Koa Error handler + * + * @param ctx - Koa CTX object instance + * @param error - Error object instance + */ +const handlerErrorKoa = ({ ctx, error }: IKoaErrorHandler) => { + error = error?.status ? error : defaultError + + ctx.type = 'json' + ctx.status = error.status + ctx.body = error + return ctx +} + +export default handlerErrorKoa diff --git a/lib/handlers/index.ts b/lib/handlers/index.ts new file mode 100644 index 0000000..c2ba4ed --- /dev/null +++ b/lib/handlers/index.ts @@ -0,0 +1,3 @@ +export { default as handlerErrorKoa } from './handlerErrorKoa' +export { default as handlerErrorExpress } from './handlerErrorExpress' +export { default as handlerErrorAdonis } from './handlerErrorAdonis' diff --git a/lib/index.ts b/lib/index.ts index ee81053..0401d0d 100644 --- a/lib/index.ts +++ b/lib/index.ts @@ -1,2 +1,2 @@ -export { default as makeRes } from './makeRes' -export { default as makeErr } from './makeErr' +export * from './builders' +export * from './handlers' diff --git a/lib/makeRes.ts b/lib/makeRes.ts deleted file mode 100644 index f9c2409..0000000 --- a/lib/makeRes.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { IMakeRes, IResponse } from './types' -import makeModelMessage from './makeModelMessage' - -/** - * @function makeRes - * - * Simple model for successful responses. - * - * @param code - HTTP status code 1xx to 3xx - * @param message - Legible action response - * @param data - Back Data - * @param title - Short and descriptive information - */ -const makeRes = ({ code, data, message, title }: IMakeRes): IResponse => - Object.assign(makeModelMessage({ code, title }), { data, message }) - -export default makeRes diff --git a/lib/types.ts b/lib/types/builders.ts similarity index 86% rename from lib/types.ts rename to lib/types/builders.ts index abf6169..fbb182c 100644 --- a/lib/types.ts +++ b/lib/types/builders.ts @@ -4,21 +4,21 @@ import { REDIRECTION, CLIENT_ERROR, SERVER_ERROR, -} from './httpCodes' +} from '../utils/httpCodes' -export interface IMakeMessage { +export interface ICreateModelMessage { code: TInformational | TSuccess | TRedirection | TClientError | TServerError title?: string } -export interface IMakeRes { +export interface ICreateResponse { code: TInformational | TSuccess | TRedirection message?: string title?: string data?: [] | object } -export interface IMakeErr { +export interface ICreateError { code: TClientError | TServerError detail: string title?: string diff --git a/lib/types/contextHttp.ts b/lib/types/contextHttp.ts new file mode 100644 index 0000000..2e1cca5 --- /dev/null +++ b/lib/types/contextHttp.ts @@ -0,0 +1,18 @@ +// Koa +export interface IKoaContext { + type: string + status: number + body: object +} + +// Express +export interface IExpressResponse { + status(code: number): this + json(body: any): void +} + +// AdonisJs +export interface IAdonisResponse { + status(code: number): this + json(body: any, generateEtag?: boolean): void +} diff --git a/lib/types/handlers.ts b/lib/types/handlers.ts new file mode 100644 index 0000000..835b26d --- /dev/null +++ b/lib/types/handlers.ts @@ -0,0 +1,20 @@ +import { IError } from './builders' +import { IAdonisResponse, IExpressResponse, IKoaContext } from './contextHttp' + +// Koa +export interface IKoaErrorHandler { + ctx: IKoaContext + error?: IError +} + +// Express +export interface IExpressErrorHandler { + res: IExpressResponse + error?: IError +} + +// AdonisJs +export interface IAdonisErrorHandler { + response: IAdonisResponse + error?: IError +} diff --git a/lib/httpCodes.ts b/lib/utils/httpCodes.ts similarity index 100% rename from lib/httpCodes.ts rename to lib/utils/httpCodes.ts diff --git a/package-lock.json b/package-lock.json index 78a6e29..af87a82 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "http-handler-response", - "version": "0.4.0", + "version": "0.5.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index c396444..5b4f3db 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "http-handler-response", - "version": "0.5.0", + "version": "0.6.0", "main": "dist/lib/index.js", "module": "dist/lib/index.es.js", "jsnext:main": "dist/lib/index.es.js",