Git Product home page Git Product logo

next-rest-api's People

Contributors

dependabot[bot] avatar satazor avatar

Stargazers

 avatar  avatar  avatar  avatar

Watchers

 avatar

next-rest-api's Issues

Adding Typescript Support

You could add support to typescript, rewriting withRest or adding compatibility through index.d.ts:

  import type { NextApiRequest, NextApiResponse } from 'next'
  import Boom from '@hapi/boom'
  import Joi from 'joi'
  
  const defaultLogError = (err: Boom.Boom) => {
    // Only log internal server errors
    if (!err.isServer) {
      return
    }
  
    // Log original error if passed
    if (err.data && err.data.originalError) {
      err = err.data.originalError
    }
  
    console.error(err.stack)
  }
  
  const defaultSendError = (res: NextApiResponse, err: Boom.Boom) => {
    const { output } = err
    const { headers, statusCode, payload } = output
  
    Object.entries(headers).forEach(([key, value]) =>
      res.setHeader(key, value || '')
    )
  
    res.status(statusCode).json(payload)
  }
  
  /**
   * Wraps a HTTP request handler with validation against Joi schemas.
   *
   * @param {object} schemas - An object with `query`, `body` or `headers` keys and their associated Joi schemas.
   *                           Each of these schemas will be matched against the incoming request.
   *
   * @returns {Function} The HTTP handler that validates the request.
   *
   * @example
   *
   * const getSchema = {
   *   query: Joi.object({
   *      id: Joi.string().required(),
   *   }),
   * };
   *
   * export default withRest({
   *   GET: withValidation(getSchema)(async req, res) => {
   *     // Do something with `req.query.id`
   *
   *     return { foo: 'bar' };
   *   },
   * });
   */
  export const withValidation =
    <T = any, R = any>(schemas: Joi.PartialSchemaMap<T> | undefined) =>
    (fn: (arg0: NextApiRequest, arg1: NextApiResponse<R>) => Promise<any>) =>
    async (req: NextApiRequest, res: NextApiResponse) => {
      const joiSchema = Joi.object(schemas).unknown(true)
  
      let validated: { [x: string]: any }
  
      try {
        validated = await joiSchema.validateAsync(req)
      } catch (err: any) {
        throw Boom.badRequest(err.message, { originalError: err as Error })
      }
  
      // Joi normalizes values, so we must copy things back to req
      ;['headers', 'body', 'query'].forEach((key: string) => {
        ;(req as any)[key] = validated[key]
      })
  
      return fn(req, res)
    }
  
  /**
   * @typedef {Function} SendError
   *
   * @param {object} res - Node.js response object.
   * @param {Error} err - The Boom error object.
   */
  /**
   * @typedef {Function} LogError
   *
   * @param {Error} err - The Boom error object.
   */
  
  /**
   * Matches handlers defined in `methods` against the HTTP method, like `GET` or `POST`.
   *
   * @param {object.<string, Function>} methods - An object mapping HTTP methods to their handlers.
   * @param {object} options - The options.
   * @param {SendError} options.sendError - A function responsible to send Boom errors back to the client.
   * @param {LogError} options.logError - A function that logs errors.
   *
   * @returns {Function} The composed HTTP handler.
   *
   * @example
   *
   * export default withRest({
   *   GET: async (req, res) => {
   *     // Do something...
   *
   *     return { foo: 'bar' };
   *   },
   * });
   */
  const withRest = (
    methods: {
      [x: string]: any
    },
    opts: {
      logError?: typeof defaultLogError
      sendError?: typeof defaultSendError
    } = {
      logError: defaultLogError,
      sendError: defaultSendError,
    }
  ) => {
    const options = {
      logError: defaultLogError,
      sendError: defaultSendError,
      ...opts,
    }
  
    return async (req: NextApiRequest, res: NextApiResponse) => {
      try {
        const method = methods && methods[req.method || 'unknown']
  
        if (!method) {
          throw Boom.methodNotAllowed(
            `Method ${req.method} is not supported for this endpoint`
          )
        }
  
        const json = await method(req, res)
  
        // Do nothing if the request is already sent (e.g.: a redirect was issued)
        if (res.headersSent) {
          if (json !== undefined) {
            options.logError(
              Boom.internal(
                'You have sent the response inside your handler but still returned something. This error was not sent to the client, however you should probably not return a value in the handler.'
              ) // eslint-disable-line max-len
            )
          }
  
          return
        }
  
        // Next.js doesn't support nulls as `RFC7159` dictates, but we do
        if (json == null) {
          res.setHeader('Content-Type', 'application/json')
          res.setHeader('Content-Length', '4')
          res.end('null')
        } else {
          res.json(json)
        }
      } catch (err: Error | Boom.Boom | any) {
        // Not an ApiError? Then wrap it into an ApiError and log it.
        let apiError = err
        if (!err.isBoom) {
          apiError = Boom.internal(undefined, { originalError: err })
        }
  
        options.logError(apiError)
        options.sendError(res, apiError)
      }
    }
  }
  
  export default withRest
  

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.