All files contractValidation.ts

100% Statements 44/44
100% Branches 15/15
100% Functions 4/4
100% Lines 44/44

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 451x 1x 1x 1x 3x 3x 3x 3x 3x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 23x 23x 23x 23x 23x 23x 3x 3x 21x 19x 19x 6x 6x 6x 5x 5x 1x 1x 23x  
import { validate, ValidationResult } from 'yaschva'
import { ContractType, AuthInput, HttpMethods, Implementation, HandleResult, isContractInError } from './globalTypes.js'
 
const inputValidationFailed = (errors:ValidationResult, data:any) => ({
  errorType: 'Input validation failed',
  data,
  status: 400,
  errors
})
 
const notImplemented = (contractName:string) => ({
  errorType: 'Not implemented',
  data: contractName,
  status: 501,
  errors: [`Handler for ${contractName} was not defined`]
})
 
const unexpectedResult = (errors: ValidationResult, data:any) => ({
  errorType: 'Unexpected result from function',
  data,
  status: 500,
  errors
})
 
export const wrapHandleWithValidation = <METHOD extends HttpMethods, IMPL extends Implementation, IN, OUT>(
  contract: ContractType<METHOD, IMPL, IN, OUT>,
  validateOutput:boolean = true
): ((input: any, auth?: AuthInput, id?:string) => Promise<HandleResult<OUT>>) => {
  return async (input: any, auth:AuthInput = {}, id?:string): Promise<HandleResult<OUT>> => {
    const validationResult = validate(contract.arguments, input)
    if (validationResult.result === 'fail') {
      return inputValidationFailed(validationResult, input)
    }
    if (contract.handle) {
      const result = await contract.handle(input, { ...auth }, contract, id)
      if (validateOutput && !isContractInError(result)) {
        const outputValidation = validate(contract.returns, result.result)
        if (outputValidation.result === 'fail') return unexpectedResult(outputValidation, result.result)
      }
      return result
    }
    return notImplemented(contract.name)
  }
}