import Ajv = require ( 'ajv' ) ; import { Message , SignedState } from './types' ; const apiSchema = require ( './generated-schema.json' ) ; const ajv = new Ajv ( ) ; ajv . addSchema ( apiSchema , 'api.json' ) ; function prettyPrintError ( e ) { switch ( e . keyword ) { case 'additionalProperties' : { const unexpected = ( e . params as any ) . additionalProperty ; return `Unexpected property '${ unexpected }' found at root${ e . dataPath } ` ; } case 'required' : { const missing = ( e . params as any ) . missingProperty ; return `Missing required property '${ missing }' at root${ e . dataPath }` ; } case 'type' : case 'pattern' : { return `Property at root${ e . dataPath } ${ e . message }` ; } } return JSON . stringify ( e ) ; } export const messageIsValid = ajv . compile ( { $ref : 'api.json#/definitions/Message' } ) ; export function validateMessage ( jsonBlob ) { if ( ! messageIsValid ( jsonBlob ) ) { throw new WireFormatValidationError ( 'Invalid message' , jsonBlob , messageIsValid . errors ?. map ( e => prettyPrintError ( e ) ) ) ; } return jsonBlob as Message ; } export const stateIsValid = ajv . compile ( { $ref : 'api.json#/definitions/SignedState' } ) ; export function validateState ( jsonBlob ) { const valid = stateIsValid ( jsonBlob ) ; if ( ! valid ) { throw new WireFormatValidationError ( 'Invalid state' , jsonBlob , stateIsValid . errors ?. map ( e => prettyPrintError ( e ) ) ) ; } return jsonBlob as SignedState ; } class WireFormatValidationError extends Error { constructor ( reason , public jsonBlob , public errorMessages ? ) { super ( reason ) ; } }