114 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			114 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
'use strict'
 | 
						|
 | 
						|
module.exports = validate
 | 
						|
 | 
						|
const { RequestError } = require('@octokit/request-error')
 | 
						|
const get = require('lodash.get')
 | 
						|
const set = require('lodash.set')
 | 
						|
 | 
						|
function validate (octokit, options) {
 | 
						|
  if (!options.request.validate) {
 | 
						|
    return
 | 
						|
  }
 | 
						|
  const { validate: params } = options.request
 | 
						|
 | 
						|
  Object.keys(params).forEach(parameterName => {
 | 
						|
    const parameter = get(params, parameterName)
 | 
						|
 | 
						|
    const expectedType = parameter.type
 | 
						|
    let parentParameterName
 | 
						|
    let parentValue
 | 
						|
    let parentParamIsPresent = true
 | 
						|
    let parentParameterIsArray = false
 | 
						|
 | 
						|
    if (/\./.test(parameterName)) {
 | 
						|
      parentParameterName = parameterName.replace(/\.[^.]+$/, '')
 | 
						|
      parentParameterIsArray = parentParameterName.slice(-2) === '[]'
 | 
						|
      if (parentParameterIsArray) {
 | 
						|
        parentParameterName = parentParameterName.slice(0, -2)
 | 
						|
      }
 | 
						|
      parentValue = get(options, parentParameterName)
 | 
						|
      parentParamIsPresent = parentParameterName === 'headers' || (typeof parentValue === 'object' && parentValue !== null)
 | 
						|
    }
 | 
						|
 | 
						|
    const values = parentParameterIsArray
 | 
						|
      ? (get(options, parentParameterName) || []).map(value => value[parameterName.split(/\./).pop()])
 | 
						|
      : [get(options, parameterName)]
 | 
						|
 | 
						|
    values.forEach((value, i) => {
 | 
						|
      const valueIsPresent = typeof value !== 'undefined'
 | 
						|
      const valueIsNull = value === null
 | 
						|
      const currentParameterName = parentParameterIsArray
 | 
						|
        ? parameterName.replace(/\[\]/, `[${i}]`)
 | 
						|
        : parameterName
 | 
						|
 | 
						|
      if (!parameter.required && !valueIsPresent) {
 | 
						|
        return
 | 
						|
      }
 | 
						|
 | 
						|
      // if the parent parameter is of type object but allows null
 | 
						|
      // then the child parameters can be ignored
 | 
						|
      if (!parentParamIsPresent) {
 | 
						|
        return
 | 
						|
      }
 | 
						|
 | 
						|
      if (parameter.allowNull && valueIsNull) {
 | 
						|
        return
 | 
						|
      }
 | 
						|
 | 
						|
      if (!parameter.allowNull && valueIsNull) {
 | 
						|
        throw new RequestError(`'${currentParameterName}' cannot be null`, 400, {
 | 
						|
          request: options
 | 
						|
        })
 | 
						|
      }
 | 
						|
 | 
						|
      if (parameter.required && !valueIsPresent) {
 | 
						|
        throw new RequestError(`Empty value for parameter '${currentParameterName}': ${JSON.stringify(value)}`, 400, {
 | 
						|
          request: options
 | 
						|
        })
 | 
						|
      }
 | 
						|
 | 
						|
      // parse to integer before checking for enum
 | 
						|
      // so that string "1" will match enum with number 1
 | 
						|
      if (expectedType === 'integer') {
 | 
						|
        const unparsedValue = value
 | 
						|
        value = parseInt(value, 10)
 | 
						|
        if (isNaN(value)) {
 | 
						|
          throw new RequestError(`Invalid value for parameter '${currentParameterName}': ${JSON.stringify(unparsedValue)} is NaN`, 400, {
 | 
						|
            request: options
 | 
						|
          })
 | 
						|
        }
 | 
						|
      }
 | 
						|
 | 
						|
      if (parameter.enum && parameter.enum.indexOf(value) === -1) {
 | 
						|
        throw new RequestError(`Invalid value for parameter '${currentParameterName}': ${JSON.stringify(value)}`, 400, {
 | 
						|
          request: options
 | 
						|
        })
 | 
						|
      }
 | 
						|
 | 
						|
      if (parameter.validation) {
 | 
						|
        const regex = new RegExp(parameter.validation)
 | 
						|
        if (!regex.test(value)) {
 | 
						|
          throw new RequestError(`Invalid value for parameter '${currentParameterName}': ${JSON.stringify(value)}`, 400, {
 | 
						|
            request: options
 | 
						|
          })
 | 
						|
        }
 | 
						|
      }
 | 
						|
 | 
						|
      if (expectedType === 'object' && typeof value === 'string') {
 | 
						|
        try {
 | 
						|
          value = JSON.parse(value)
 | 
						|
        } catch (exception) {
 | 
						|
          throw new RequestError(`JSON parse error of value for parameter '${currentParameterName}': ${JSON.stringify(value)}`, 400, {
 | 
						|
            request: options
 | 
						|
          })
 | 
						|
        }
 | 
						|
      }
 | 
						|
 | 
						|
      set(options, parameter.mapTo || currentParameterName, value)
 | 
						|
    })
 | 
						|
  })
 | 
						|
 | 
						|
  return options
 | 
						|
}
 |