import { ButteryFile , Reference , Service , VariableDeclaration , OneOfType , } from "./ast" ; import { left , right , Either } from "fp-ts/lib/Either" ; export function validate ( file ) { const hasOnlyStructsAndServices = file . variables . every ( ( decl ) => decl . value . type !== "rpc" && decl . value . type !== "channel" ) ; if ( ! hasOnlyStructsAndServices ) { return right ( new Error ( `${ file . path } has rpc definitions outside of channels` ) ) ; } const noNestedServices = ( file . variables . map ( ( decl ) => decl . value ) . filter ( ( decl ) => decl . type === "service" ) as Service < Reference > [ ] ) . every ( ( service ) => service . variables . every ( ( varInService ) => varInService . value . type !== "service" ) ) ; if ( ! noNestedServices ) { return right ( new Error ( `Cannot nest services` ) ) ; } const ensureNoRepeats = ( variables ) => { const acc = { } ; for ( let { name } of variables ) { if ( acc [ name ] ) { throw new Error ( `Repeated variable ${ name } in ${ file . path }` ) ; } acc [ name ] = true ; } } ; try { ensureNoRepeats ( file . variables ) ; file . variables . filter ( ( decl ) => decl . value . type === "service" ) . forEach ( ( decl ) => { ensureNoRepeats ( ( decl . value as Service < unknown > ) . variables ) ; } ) ; } catch ( e ) { return right ( e ) ; } return left ( file ) ; }