简体   繁体   中英

Refactoring hapi configs with joi validation

I have hapi routes configs, which contains validation and I want to move this validation from config to file with validations for this model. For example for PATCH for users:

const routeConfig = {
  method: 'PATCH',
  path: '/users/{id}',
  config: {
    ...
    validate: {
      params: {
        id: Joi.string().required()
      },
      payload: {
        email: Joi.string().email().optional(),
        password: Joi.string().optional(),
        fieldA: Joi.string().optional(),
        fieldB: {
          fieldB1: Joi.string().optional(),
          fieldB2: Joi.string().optional(),
          fieldB3: Joi.string().uri().optional(),
          fieldB4: Joi.string().uri().optional(),
          fieldB5: {
            fieldB6: Joi.string().optional(),
            fieldB7: Joi.string().optional(),
            fieldB8: Joi.string().optional()
          }
        }
      }
    },
    handler
  }
}

On POST:

const routeConfig = {
  method: 'POST',
  path: '/users',
  config: {
    ...
    validate: {
      email: Joi.string().email().required(),
      password: Joi.string().required(),
      confirmPassword: Joi.string().required()
    },
    handler
  }
}

How you can see, for create and update used different fields. Also, I have routes, wich related to another model, like this:

const routeConfig = {
  method: 'PUT',
  path: '/users/{id}/updateRelated',
  config: {
    validate: {
      params: {
        id: Joi.string().required()
      },
      payload: {
        relatedId: Joi.string().required(),
        relatedModelFieldA: Joi.string().required(),
        relatedModelFieldB: Joi.string().required(),
        relatedModelFieldC: Joi.string().required(),
        ... 10 fields
      }
    }
  }
}

Only for model I can move to validator with structure:

const validationSchemas = {
  'post-users': {
    payload: ...
  }
  'patch-users': {
    params: ...,
    payload: ...
  },
  ...
}

But how include related routes? Because payload for PUT updateRelated is equivalent to PUT on this related models(ex: PUT /users/{user_id}/modelA equivalent PUT /modelA/{modelA_id})

Also, another endpoint can receive data for user model. For example: /me/coords can update coords field in user model, where payload will contain only latitude and longitude types.

Thanks!

Create an export for your Id validation which would be common across multiple routes like

const Joi = require('joi');

module.exports = Joi.object({
   id: Joi.string().required()
});

Then for each of your different payload validations create an export of for it. ie

const Joi = require('joi');

module.exports = Joi.object({
    email: Joi.string().email().optional(),
    password: Joi.string().optional(),
    fieldA: Joi.string().optional(),
    fieldB: {
      fieldB1: Joi.string().optional(),
      fieldB2: Joi.string().optional(),
      fieldB3: Joi.string().uri().optional(),
      fieldB4: Joi.string().uri().optional(),
      fieldB5: {
        fieldB6: Joi.string().optional(),
        fieldB7: Joi.string().optional(),
        fieldB8: Joi.string().optional()
      }
    }
});

Then require them in your route and use them as part of the validate object. ie

const idParamsSchema = require('./id-param-schema');
const payloadSchema = require('./payload-schema');

...

const routeConfig = {
  method: 'PUT',
  path: '/users/{id}/updateRelated',
  config: {
     validate: {
        params: idParamsSchema,
        payload: payloadSchema
     }
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM