11import { QueryTreeNode } from './query-tree' ;
2- import { ValueTreeNode } from './value-tree ' ;
2+ import { ResultTree } from './result ' ;
33import { ITransport } from './transport' ;
4- import { ClientBus } from './client-bus ' ;
4+ import { RunningQuery } from './running-query ' ;
55import {
66 ObservableQuery ,
77 IQueryOptions ,
88} from './query' ;
99import {
10- Mutation ,
1110 IMutationOptions ,
1211} from './mutation' ;
13- import {
14- ISoyuzClientContext ,
15- ISoyuzSerialOperation ,
16- } from './interfaces' ;
1712import { parse , OperationDefinitionNode } from 'graphql' ;
1813import { simplifyQueryAst } from './util/graphql' ;
1914import { BehaviorSubject } from 'rxjs/BehaviorSubject' ;
15+ import { Subscription } from 'rxjs/Subscription' ;
2016
2117// Soyuz client.
2218export class SoyuzClient {
23- private queryTree : QueryTreeNode ;
24- private context = new BehaviorSubject < ISoyuzClientContext > ( null ) ;
19+ // queryTree holds the global live query tree.
20+ private queryTree : QueryTreeNode = new QueryTreeNode ( ) ;
2521 private transportIdCounter = 0 ;
26-
27- // Active serial operations in-flight.
28- private serialOperations : { [ operationId : number ] : ISoyuzSerialOperation } = { } ;
29- private serialOperationIdCounter = 0 ;
30-
31- constructor ( ) {
32- this . queryTree = new QueryTreeNode ( ) ;
33- this . initHandlers ( ) ;
34- }
22+ private transport : ITransport ;
23+ private queries : { [ id : number ] : RunningQuery } = { } ;
24+ private primaryQueryId : number ;
25+ private primaryResultTree : BehaviorSubject < ResultTree > = new BehaviorSubject < ResultTree > ( null ) ;
26+ private transportSubs : Subscription [ ] = [ ] ;
3527
3628 // Set transport causes the client to start using a new transport to talk to the server.
3729 // Pass null to stop using the previous transport.
3830 public setTransport ( transport : ITransport ) {
39- if ( this . context . value && this . context . value . transport === transport ) {
31+ if ( this . transport === transport ) {
4032 return ;
4133 }
4234
35+ if ( this . transport ) {
36+ for ( let queryId in this . queries ) {
37+ if ( ! this . queries . hasOwnProperty ( queryId ) ) {
38+ continue ;
39+ }
40+ this . queries [ queryId ] . dispose ( ) ;
41+ }
42+ this . queries = { } ;
43+ for ( let sub of this . transportSubs ) {
44+ sub . unsubscribe ( ) ;
45+ }
46+ this . transportSubs . length = 0 ;
47+ }
48+
4349 if ( ! transport ) {
44- this . context . next ( null ) ;
4550 return ;
4651 }
4752
4853 let tid : number = this . transportIdCounter ++ ;
49- let vtr = new ValueTreeNode ( this . queryTree ) ;
50- let clib = new ClientBus ( transport , this . queryTree , vtr , this . serialOperations ) ;
51- this . context . next ( {
52- transport : transport ,
53- valueTree : vtr ,
54- clientBus : clib ,
55- } ) ;
54+ // start the initial root query
55+ let query = new RunningQuery ( transport , this . queryTree , 'query' ) ;
56+ this . transportSubs . push ( query . resultTree . subscribe ( ( tree ) => {
57+ this . primaryResultTree . next ( tree ) ;
58+ } ) ) ;
59+ this . primaryQueryId = query . id ;
60+ this . queries = { } ;
61+ this . queries [ query . id ] = query ;
62+ query . resultTree . subscribe ( { complete : ( ) => {
63+ if ( this . queries [ query . id ] === query ) {
64+ delete this . queries [ query . id ] ;
65+ }
66+ } } ) ;
5667 }
5768
5869 // Build a query against the system.
59- public query < T > ( options : IQueryOptions ) : ObservableQuery < T > {
70+ public query < T > ( options : IQueryOptions ) : ObservableQuery {
6071 if ( ! options || ! options . query ) {
6172 throw new Error ( 'You must specify a options object and query.' ) ;
6273 }
@@ -70,10 +81,7 @@ export class SoyuzClient {
7081 if ( ! odef ) {
7182 throw new Error ( 'Your provided query document did not contain a query definition.' ) ;
7283 }
73- return new ObservableQuery < T > ( this . context ,
74- this . queryTree ,
75- odef ,
76- options . variables ) ;
84+ return new ObservableQuery ( this . primaryResultTree , this . queryTree , odef , options . variables ) ;
7785 }
7886
7987 // Execute a mutation against the system.
@@ -91,27 +99,29 @@ export class SoyuzClient {
9199 if ( ! odef ) {
92100 throw new Error ( 'Your provided mutation document did not contain a mutation definition.' ) ;
93101 }
94- let operationId = ++ this . serialOperationIdCounter ;
95- let mutation : ISoyuzSerialOperation = new Mutation < T > ( operationId , this . context , odef , options . variables ) ;
96- this . startSerialOperation ( operationId , mutation ) ;
97- return mutation . asPromise ( ) ;
98- }
99-
100- // startSerialOperation begins a already-built operation.
101- private startSerialOperation ( id : number , operation : ISoyuzSerialOperation ) {
102- this . serialOperations [ id ] = operation ;
103- operation . init ( ) ;
104- }
105-
106- private initHandlers ( ) {
107- let lastContext : ISoyuzClientContext ;
108- this . context . subscribe ( ( ctx ) => {
109- if ( lastContext ) {
110- lastContext . valueTree . dispose ( ) ;
111- lastContext . clientBus . dispose ( ) ;
102+ // start the query.
103+ let qt = new QueryTreeNode ( ) ;
104+ let qr = new RunningQuery ( this . transport , qt , 'mutation' ) ;
105+ let uqr = qt . buildQuery ( odef , options . variables || { } ) ;
106+ this . queries [ qr . id ] = qr ;
107+ let lrt : any ;
108+ let data : any ;
109+ let rtsub = qr . resultTree . subscribe ( ( rt ) => {
110+ if ( ! rt || rt === lrt ) {
111+ return ;
112112 }
113-
114- lastContext = ctx ;
113+ lrt = rt ;
114+ data = rt . addQuery ( uqr . id , ( id ) => { } ) ;
115+ } ) ;
116+ return new Promise < T > ( ( reject , resolve ) => {
117+ qr . resultTree . subscribe ( {
118+ error : ( err ) => {
119+ reject ( err ) ;
120+ } ,
121+ complete : ( ) => {
122+ resolve ( data ) ;
123+ } ,
124+ } ) ;
115125 } ) ;
116126 }
117127}
0 commit comments