import { RunningQuery } from './query' ; import { QueryTree } from '../query-tree/query-tree' ; import { ResultTree } from '../result-tree/result-tree' ; import { GraphQLSchema , OperationDefinitionNode , parse } from 'graphql' ; import { rgraphql } from 'rgraphql' ; import { Query } from '../query-tree/query' ; export class SoyuzClient { private queryTree : QueryTree ; private resultTree : ResultTree ; private queries : { [ key ] : RunningQuery ; } = { } ; private queryID : number = 1 ; private resultID : number = 0 ; constructor ( private schema , private sendMsg ) { this . queryTree = new QueryTree ( schema , this . handleTreeMutation . bind ( this ) ) ; this . resultTree = new ResultTree ( this . queryTree , rgraphql . RGQLValueInit . CacheStrategy . CACHE_LRU , 100 ) ; sendMsg ( { initQuery : { queryId : this . queryID } } ) ; } public buildQuery ( ast , variables ? ) { let uquery = this . queryTree . buildQuery ( ast , variables ) ; let rq = new RunningQuery ( uquery , this . resultTree , ( ) => { this . disposeQuery ( uquery ) ; } ) ; this . queries [ rq . getQuery ( ) . getQueryID ( ) ] = rq ; return rq ; } public parseQuery ( source , variables ? ) { let defs = parse ( source ) ; let def ; for ( let defi of defs . definitions ) { if ( defi . kind === 'OperationDefinition' && defi . operation ) { def = defi ; } } if ( ! def ) { throw new Error ( 'no query definition found in source' ) ; } return this . buildQuery ( def , variables ) ; } public getQueryTree ( ) { return this . queryTree ; } public handleMessages ( msgs ) { for ( let msg of msgs ) { if ( msg . valueInit ) { if ( msg . valueInit . queryId !== this . queryID ) { continue ; } this . resultID = msg . valueInit . resultId || 0 ; } if ( msg . valueBatch && msg . valueBatch . resultId === this . resultID && msg . valueBatch . values ) { for ( let valueBin of msg . valueBatch . values ) { let val = rgraphql . RGQLValue . decode ( valueBin ) ; this . resultTree . handleValue ( val ) ; } } } this . resultTree . flushHandlers ( ) ; } private handleTreeMutation ( mut ) { this . sendMsg ( { mutateTree : { queryId : this . queryID , nodeMutation : mut . nodeMutation , variables : mut . variables } } ) ; } private disposeQuery ( query ) { this . queryTree . detach ( query ) ; delete this . queries [ query . getQueryID ( ) ] ; } public dispose ( ) { this . sendMsg ( { finishQuery : { queryId : this . queryID } } ) ; } }