@@ -44,7 +44,7 @@ class MiddlewareApp extends React.Component<Props, State> {
4444 subscriptionEndpoint :
4545 props . subscriptionEndpoint ||
4646 getParameterByName ( 'subscriptionEndpoint' ) ||
47- getSubscriptionsUrl ( endpoint ) ,
47+ '' ,
4848 }
4949 }
5050
@@ -56,14 +56,18 @@ class MiddlewareApp extends React.Component<Props, State> {
5656 }
5757 }
5858
59+ componentDidMount ( ) {
60+ if ( this . state . subscriptionEndpoint === '' ) {
61+ this . updateSubscriptionsUrl ( )
62+ }
63+ }
64+
5965 render ( ) {
60- const title = this . props . setTitle
61- ? < Helmet >
62- < title >
63- { this . getTitle ( ) }
64- </ title >
65- </ Helmet >
66- : null
66+ const title = this . props . setTitle ? (
67+ < Helmet >
68+ < title > { this . getTitle ( ) } </ title >
69+ </ Helmet >
70+ ) : null
6771
6872 return (
6973 < div >
@@ -134,7 +138,7 @@ class MiddlewareApp extends React.Component<Props, State> {
134138 this . state . platformToken ||
135139 this . state . endpoint . includes ( 'api.graph.cool' )
136140 ) {
137- const projectId = getProjectId ( this . state . endpoint )
141+ const projectId = this . getProjectId ( this . state . endpoint )
138142 const cluster = this . state . endpoint . includes ( 'api.graph.cool' )
139143 ? 'shared'
140144 : 'local'
@@ -143,22 +147,76 @@ class MiddlewareApp extends React.Component<Props, State> {
143147
144148 return `Playground - ${ this . state . endpoint } `
145149 }
146- }
147150
148- export default MiddlewareApp
151+ private async updateSubscriptionsUrl ( ) {
152+ const candidates = this . getSubscriptionsUrlCandidated ( this . state . endpoint )
153+ const validCandidate = await find ( candidates , candidate =>
154+ this . wsEndpointValid ( candidate ) ,
155+ )
156+ if ( validCandidate ) {
157+ this . setState ( { subscriptionEndpoint : validCandidate } )
158+ }
159+ }
160+
161+ private getSubscriptionsUrlCandidated ( endpoint ) : string [ ] {
162+ const candidates : string [ ] = [ ]
163+ candidates . push ( endpoint . replace ( 'https' , 'wss' ) . replace ( 'http' , 'ws' ) )
164+ if ( endpoint . includes ( 'graph.cool' ) ) {
165+ candidates . push (
166+ `wss://subscriptions.graph.cool/v1/${ this . getProjectId ( endpoint ) } ` ,
167+ )
168+ }
169+ if ( endpoint . includes ( '/simple/v1/' ) ) {
170+ // it's a graphcool local endpoint
171+ const host = endpoint . match ( / h t t p s ? : \/ \/ ( .* ?) \/ / )
172+ candidates . push (
173+ `ws://${ host ! [ 1 ] } /subscriptions/v1/${ this . getProjectId ( endpoint ) } ` ,
174+ )
175+ }
176+ return candidates
177+ }
149178
150- function getSubscriptionsUrl ( endpoint ) : string | undefined {
151- if ( endpoint . includes ( 'graph.cool' ) ) {
152- return `wss://subscriptions.graph.cool/v1/${ getProjectId ( endpoint ) } `
179+ private wsEndpointValid ( url ) : Promise < boolean > {
180+ return new Promise ( resolve => {
181+ const socket = new WebSocket (
182+ 'wss://subscriptions.graph.cool/v1/cirs1ufsg02b101619ru0bx5r' ,
183+ 'graphql-ws' ,
184+ )
185+ socket . addEventListener ( 'open' , event => {
186+ socket . send ( JSON . stringify ( { type : 'connection_init' } ) )
187+ } )
188+ socket . addEventListener ( 'message' , event => {
189+ const data = JSON . parse ( event . data )
190+ if ( data . type === 'connection_ack' ) {
191+ resolve ( true )
192+ }
193+ } )
194+ socket . addEventListener ( 'error' , event => {
195+ resolve ( false )
196+ } )
197+ setTimeout ( ( ) => {
198+ resolve ( false )
199+ } , 1000 )
200+ } )
153201 }
154- if ( endpoint . includes ( '/simple/v1/' ) ) {
155- // it's a graphcool local endpoint
156- const host = endpoint . match ( / h t t p s ? : \/ \/ ( .* ?) \/ / )
157- return `ws://${ host ! [ 1 ] } /subscriptions/v1/${ getProjectId ( endpoint ) } `
202+
203+ private getProjectId ( endpoint ) {
204+ return endpoint . split ( '/' ) . slice ( - 1 ) [ 0 ]
158205 }
159- return undefined
160206}
161207
162- function getProjectId ( endpoint ) {
163- return endpoint . split ( '/' ) . slice ( - 1 ) [ 0 ]
208+ async function find (
209+ iterable : any [ ] ,
210+ predicate : ( item ?: any , index ?: number ) => Promise < boolean > ,
211+ ) : Promise < any | null > {
212+ for ( let i = 0 ; i < iterable . length ; i ++ ) {
213+ const element = iterable [ i ]
214+ const result = await predicate ( element , i )
215+ if ( result ) {
216+ return element
217+ }
218+ }
219+ return null
164220}
221+
222+ export default MiddlewareApp
0 commit comments