@@ -7,14 +7,26 @@ process.env.NODE_TLS_REJECT_UNAUTHORIZED = 0;
77const { app, BrowserWindow, TouchBar, ipcMain } = require ( 'electron' ) ;
88const path = require ( 'path' ) ;
99const url = require ( 'url' ) ;
10- // This allows electron to spin up this server to localhost:7000 when the app starts up
11- require ( './httpserver' ) ;
10+
1211// Import Auto-Updater- Swell will update itself
1312const { autoUpdater } = require ( 'electron-updater' ) ;
1413const log = require ( 'electron-log' ) ;
1514// TouchBarButtons are our nav buttons(ex: Select All, Deselect All, Open Selected, Close Selected, Clear All)
1615const { TouchBarButton, TouchBarSpacer } = TouchBar ;
1716
17+ // basic http cookie parser
18+ const cookie = require ( 'cookie' ) ;
19+ // node-fetch for the fetch request
20+ const fetch2 = require ( 'node-fetch' ) ;
21+
22+ // GraphQL imports
23+ const ApolloClient = require ( 'apollo-client' ) . ApolloClient ;
24+ const gql = require ( 'graphql-tag' ) ;
25+ const { InMemoryCache } = require ( 'apollo-cache-inmemory' ) ;
26+ const { createHttpLink } = require ( 'apollo-link-http' ) ;
27+ const { ApolloLink } = require ( 'apollo-link' ) ;
28+ const { onError } = require ( "apollo-link-error" ) ;
29+
1830// configure logging
1931autoUpdater . logger = log ;
2032autoUpdater . logger . transports . file . level = 'info' ;
@@ -126,7 +138,7 @@ function createWindow() {
126138 webPreferences : {
127139 "nodeIntegration" : true ,
128140 "sandbox" : false ,
129- webSecurity : false ,
141+ webSecurity : true ,
130142 } ,
131143 icon : `${ __dirname } /src/assets/icons/64x64.png`
132144 } )
@@ -263,3 +275,125 @@ app.on('activate', () => {
263275 createWindow ( ) ;
264276 }
265277} ) ;
278+
279+
280+ // ipcMain listener that
281+ ipcMain . on ( 'http1-fetch-message' , ( event , arg ) => {
282+ const { method, headers, body } = arg . options ;
283+
284+ fetch2 ( headers . url , { method, headers, body } )
285+ . then ( ( response ) => {
286+ const headers = response . headers . raw ( ) ;
287+ // check if the endpoint sends SSE
288+ // add status code for regular http requests in the response header
289+
290+ if ( headers [ 'content-type' ] [ 0 ] . includes ( 'stream' ) ) {
291+ // invoke another func that fetches to SSE and reads stream
292+ // params: method, headers, body
293+ event . sender . send ( 'http1-fetch-reply' , { headers, body : { error : 'This Is An SSE endpoint' } } )
294+ }
295+ else {
296+ headers [ ':status' ] = response . status ;
297+
298+ const receivedCookie = headers [ 'set-cookie' ] ;
299+ headers . cookies = receivedCookie ;
300+
301+ const contents = / j s o n / . test ( response . headers . get ( 'content-type' ) ) ? response . json ( ) : response . text ( ) ;
302+ contents
303+ . then ( body => {
304+ event . sender . send ( 'http1-fetch-reply' , { headers, body } )
305+ } )
306+ . catch ( error => console . log ( 'ERROR' , error ) )
307+ }
308+ } )
309+ . catch ( error => console . log ( error ) )
310+ } )
311+
312+ ipcMain . on ( 'open-gql' , ( event , args ) => {
313+ const reqResObj = args . reqResObj ;
314+
315+ // populating headers object with response headers - except for Content-Type
316+ const headers = { } ;
317+ reqResObj . request . headers . filter ( item => item . key !== 'Content-Type' ) . forEach ( ( item ) => {
318+ headers [ item . key ] = item . value ;
319+ } ) ;
320+
321+ // request cookies from reqResObj to request headers
322+ let cookies ;
323+ if ( reqResObj . request . cookies . length ) {
324+ cookies = reqResObj . request . cookies . reduce ( ( acc , userCookie ) => {
325+ return acc + `${ userCookie . key } =${ userCookie . value } ; ` ;
326+ } , "" )
327+ }
328+ headers . Cookie = cookies ;
329+
330+ // afterware takes headers from context response object, copies to reqResObj
331+ const afterLink = new ApolloLink ( ( operation , forward ) => {
332+ return forward ( operation ) . map ( response => {
333+ const context = operation . getContext ( ) ;
334+ const headers = context . response . headers . entries ( ) ;
335+ for ( let headerItem of headers ) {
336+ const key = headerItem [ 0 ] . split ( '-' ) . map ( item => item [ 0 ] . toUpperCase ( ) + item . slice ( 1 ) ) . join ( '-' ) ;
337+ reqResObj . response . headers [ key ] = headerItem [ 1 ] ;
338+
339+ // if cookies were sent by server, parse first key-value pair, then cookie.parse the rest
340+ if ( headerItem [ 0 ] === 'set-cookie' ) {
341+ const parsedCookies = [ ] ;
342+ const cookieStrArr = headerItem [ 1 ] . split ( ', ' ) ;
343+ cookieStrArr . forEach ( thisCookie => {
344+ thisCookie = thisCookie . toLowerCase ( ) ;
345+ // index of first semicolon
346+ const idx = thisCookie . search ( / [ ; ] / g) ;
347+ // first key value pair
348+ const keyValueArr = thisCookie . slice ( 0 , idx ) . split ( '=' ) ;
349+ // cookie contents after first key value pair
350+ const parsedRemainingCookieProperties = cookie . parse ( thisCookie . slice ( idx + 1 ) ) ;
351+
352+ const parsedCookie = { ...parsedRemainingCookieProperties , name : keyValueArr [ 0 ] , value : keyValueArr [ 1 ] } ;
353+
354+ parsedCookies . push ( parsedCookie ) ;
355+ } )
356+ reqResObj . response . cookies = parsedCookies ;
357+ }
358+ }
359+
360+ return response ;
361+ } ) ;
362+ } ) ;
363+
364+ // creates http connection to host
365+ const httpLink = createHttpLink ( { uri : reqResObj . url , headers, credentials : 'include' , fetch : fetch2 , } ) ;
366+
367+ // additive composition of multiple links
368+ const link = ApolloLink . from ( [
369+ afterLink ,
370+ httpLink
371+ ] ) ;
372+
373+ const client = new ApolloClient ( {
374+ link,
375+ cache : new InMemoryCache ( ) ,
376+ } ) ;
377+
378+ const body = gql `${ reqResObj . request . body } ` ;
379+ const variables = reqResObj . request . bodyVariables ? JSON . parse ( reqResObj . request . bodyVariables ) : { } ;
380+
381+ if ( reqResObj . request . method === 'QUERY' ) {
382+ client . query ( { query : body , variables } )
383+
384+ . then ( data => {
385+ event . sender . send ( 'reply-gql' , { reqResObj, data} ) } )
386+ . catch ( ( err ) => {
387+ console . error ( err ) ;
388+ event . sender . send ( 'reply-gql' , { error : err . networkError , reqResObj} ) ;
389+ } ) ;
390+ }
391+ else if ( reqResObj . request . method === 'MUTATION' ) {
392+ client . mutate ( { mutation : body , variables } )
393+ . then ( data => event . sender . send ( 'reply-gql' , { reqResObj, data} ) )
394+ . catch ( ( err ) => {
395+ console . error ( err ) ;
396+ } ) ;
397+ }
398+ } ) ;
399+
0 commit comments