| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230 | 
							- import fs from 'node:fs/promises'
 
- import http from 'node:http'
 
- import https from 'node:https'
 
- import { ApolloServer } from 'apollo-server-express'
 
- import { isEmpty } from 'lodash-es'
 
- import { Server as IoServer } from 'socket.io'
 
- import { ApolloServerPluginLandingPageGraphQLPlayground, ApolloServerPluginLandingPageProductionDefault } from 'apollo-server-core'
 
- import graphqlUploadExpress from 'graphql-upload/graphqlUploadExpress.mjs'
 
- import { initSchema } from '../graph/index.mjs'
 
- export default {
 
-   graph: null,
 
-   http: null,
 
-   https: null,
 
-   ws: null,
 
-   connections: new Map(),
 
-   le: null,
 
-   /**
 
-    * Initialize HTTP Server
 
-    */
 
-   async initHTTP () {
 
-     WIKI.logger.info(`HTTP Server on port: [ ${WIKI.config.port} ]`)
 
-     this.http = http.createServer(WIKI.app)
 
-     this.http.on('error', (error) => {
 
-       if (error.syscall !== 'listen') {
 
-         throw error
 
-       }
 
-       switch (error.code) {
 
-         case 'EACCES':
 
-           WIKI.logger.error('Listening on port ' + WIKI.config.port + ' requires elevated privileges!')
 
-           return process.exit(1)
 
-         case 'EADDRINUSE':
 
-           WIKI.logger.error('Port ' + WIKI.config.port + ' is already in use!')
 
-           return process.exit(1)
 
-         default:
 
-           throw error
 
-       }
 
-     })
 
-     this.http.on('listening', () => {
 
-       WIKI.logger.info('HTTP Server: [ RUNNING ]')
 
-     })
 
-     this.http.on('connection', conn => {
 
-       let connKey = `http:${conn.remoteAddress}:${conn.remotePort}`
 
-       this.connections.set(connKey, conn)
 
-       conn.on('close', () => {
 
-         this.connections.delete(connKey)
 
-       })
 
-     })
 
-   },
 
-   /**
 
-    * Start HTTP Server
 
-    */
 
-   async startHTTP () {
 
-     this.http.listen(WIKI.config.port, WIKI.config.bindIP)
 
-   },
 
-   /**
 
-    * Initialize HTTPS Server
 
-    */
 
-   async initHTTPS () {
 
-     if (WIKI.config.ssl.provider === 'letsencrypt') {
 
-       this.le = require('./letsencrypt')
 
-       await this.le.init()
 
-     }
 
-     WIKI.logger.info(`HTTPS Server on port: [ ${WIKI.config.ssl.port} ]`)
 
-     const tlsOpts = {}
 
-     try {
 
-       if (WIKI.config.ssl.format === 'pem') {
 
-         tlsOpts.key = WIKI.config.ssl.inline ? WIKI.config.ssl.key : await fs.readFile(WIKI.config.ssl.key, 'utf-8')
 
-         tlsOpts.cert = WIKI.config.ssl.inline ? WIKI.config.ssl.cert : await fs.readFile(WIKI.config.ssl.cert, 'utf-8')
 
-       } else {
 
-         tlsOpts.pfx = WIKI.config.ssl.inline ? WIKI.config.ssl.pfx : await fs.readFile(WIKI.config.ssl.pfx, 'utf-8')
 
-       }
 
-       if (!isEmpty(WIKI.config.ssl.passphrase)) {
 
-         tlsOpts.passphrase = WIKI.config.ssl.passphrase
 
-       }
 
-       if (!isEmpty(WIKI.config.ssl.dhparam)) {
 
-         tlsOpts.dhparam = WIKI.config.ssl.dhparam
 
-       }
 
-     } catch (err) {
 
-       WIKI.logger.error('Failed to setup HTTPS server parameters:')
 
-       WIKI.logger.error(err)
 
-       return process.exit(1)
 
-     }
 
-     this.https = https.createServer(tlsOpts, WIKI.app)
 
-     this.https.listen(WIKI.config.ssl.port, WIKI.config.bindIP)
 
-     this.https.on('error', (error) => {
 
-       if (error.syscall !== 'listen') {
 
-         throw error
 
-       }
 
-       switch (error.code) {
 
-         case 'EACCES':
 
-           WIKI.logger.error('Listening on port ' + WIKI.config.ssl.port + ' requires elevated privileges!')
 
-           return process.exit(1)
 
-         case 'EADDRINUSE':
 
-           WIKI.logger.error('Port ' + WIKI.config.ssl.port + ' is already in use!')
 
-           return process.exit(1)
 
-         default:
 
-           throw error
 
-       }
 
-     })
 
-     this.https.on('listening', () => {
 
-       WIKI.logger.info('HTTPS Server: [ RUNNING ]')
 
-     })
 
-     this.https.on('connection', conn => {
 
-       let connKey = `https:${conn.remoteAddress}:${conn.remotePort}`
 
-       this.connections.set(connKey, conn)
 
-       conn.on('close', () => {
 
-         this.connections.delete(connKey)
 
-       })
 
-     })
 
-   },
 
-   /**
 
-    * Start HTTPS Server
 
-    */
 
-   async startHTTPS () {
 
-     this.https.listen(WIKI.config.ssl.port, WIKI.config.bindIP)
 
-   },
 
-   /**
 
-    * Start GraphQL Server
 
-    */
 
-   async startGraphQL () {
 
-     const graphqlSchema = await initSchema()
 
-     this.graph = new ApolloServer({
 
-       schema: graphqlSchema,
 
-       csrfPrevention: true,
 
-       cache: 'bounded',
 
-       context: ({ req, res }) => ({ req, res }),
 
-       plugins: [
 
-         process.env.NODE_ENV === 'development' ? ApolloServerPluginLandingPageGraphQLPlayground({
 
-           footer: false
 
-         }) : ApolloServerPluginLandingPageProductionDefault({
 
-           footer: false
 
-         })
 
-         // ApolloServerPluginDrainHttpServer({ httpServer: this.http })
 
-         // ...(this.https && ApolloServerPluginDrainHttpServer({ httpServer: this.https }))
 
-       ]
 
-     })
 
-     await this.graph.start()
 
-     WIKI.app.use(graphqlUploadExpress({
 
-       maxFileSize: WIKI.config.security.uploadMaxFileSize,
 
-       maxFiles: WIKI.config.security.uploadMaxFiles
 
-     }))
 
-     this.graph.applyMiddleware({ app: WIKI.app, cors: false, path: '/_graphql' })
 
-   },
 
-   /**
 
-    * Start Socket.io WebSocket Server
 
-    */
 
-   async initWebSocket() {
 
-     if (this.https) {
 
-       this.ws = new IoServer(this.https, {
 
-         path: '/_ws/',
 
-         serveClient: false
 
-       })
 
-       WIKI.logger.info(`WebSocket Server attached to HTTPS Server [ OK ]`)
 
-     } else {
 
-       this.ws = new IoServer(this.http, {
 
-         path: '/_ws/',
 
-         serveClient: false,
 
-         cors: true // TODO: dev only, replace with app settings once stable
 
-       })
 
-       WIKI.logger.info(`WebSocket Server attached to HTTP Server [ OK ]`)
 
-     }
 
-   },
 
-   /**
 
-    * Close all active connections
 
-    */
 
-   closeConnections (mode = 'all') {
 
-     for (const [key, conn] of this.connections) {
 
-       if (mode !== `all` && key.indexOf(`${mode}:`) !== 0) {
 
-         continue
 
-       }
 
-       conn.destroy()
 
-       this.connections.delete(key)
 
-     }
 
-     if (mode === 'all') {
 
-       this.connections.clear()
 
-     }
 
-   },
 
-   /**
 
-    * Stop all servers
 
-    */
 
-   async stopServers () {
 
-     this.closeConnections()
 
-     if (this.http) {
 
-       await new Promise(resolve => this.http.close(resolve))
 
-       this.http = null
 
-     }
 
-     if (this.https) {
 
-       await new Promise(resolve => this.https.close(resolve))
 
-       this.https = null
 
-     }
 
-     this.graph = null
 
-   },
 
-   /**
 
-    * Restart Server
 
-    */
 
-   async restartServer (srv = 'https') {
 
-     this.closeConnections(srv)
 
-     switch (srv) {
 
-       case 'http':
 
-         if (this.http) {
 
-           await new Promise(resolve => this.http.close(resolve))
 
-           this.http = null
 
-         }
 
-         this.initHTTP()
 
-         this.startHTTP()
 
-         break
 
-       case 'https':
 
-         if (this.https) {
 
-           await new Promise(resolve => this.https.close(resolve))
 
-           this.https = null
 
-         }
 
-         this.initHTTPS()
 
-         this.startHTTPS()
 
-         break
 
-       default:
 
-         throw new Error('Cannot restart server: Invalid designation')
 
-     }
 
-   }
 
- }
 
 
  |