UNPKG

reiso

Version:
286 lines 27.3 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const express = require("express"); const bodyParser = require("body-parser"); const http = require("http"); const cookieParser = require("cookie-parser"); const helmet = require("helmet"); const graphqlHTTP = require("apollo-server-express"); const graphql = require("graphql"); const subscriptionServer = require("subscriptions-transport-ws"); const multer = require("multer"); const fs = require("fs"); const path = require("path"); const compression = require("compression"); const seaport = require("seaport"); const ddos = require('ddos'); const Config_1 = require("../Modules/Config"); const Translation = require("../Modules/Translation"); const Query = require("../Modules/Query"); const Log = require("../Modules/Log"); const WebHook = require("../Modules/WebHook"); const Hooks = require("../Modules/ServerHook"); const Render_1 = require("../Server/Render"); const Error_1 = require("./Lib/Error"); const Url_1 = require("./Lib/Url"); const Translation_1 = require("./Lib/Translation"); class Server { async start() { await this.init(); await this.setBasic(); await this.setHelmet(); await this.setStatic(); await this.setLogger(); await this.setFileUpload(); await this.setGraphQL(); await this.setWebHook(); await this.setRender(); await this.setSubscription(); await this.setLogError(); await this.run(); } async stop() { await Promise.all([ new Promise(r => this.websocketServer.close(r)), new Promise(r => this.server.close(r)) ]); } init() { this.app = express(); } setBasic() { Config_1.getConfig().port && this.app.set('port', Config_1.getConfig().port); this.app.use(cookieParser()); this.app.use((req, res, next) => { res.header("Access-Control-Allow-Origin", "*"); res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept"); next(); }); this.app.use(bodyParser.urlencoded({ extended: true })); this.app.use(bodyParser.json()); this.app.use(compression()); } setHelmet() { if (Config_1.getConfig().proxyProtection) this.app.set('trust proxy', 1); this.app.use(helmet()); this.app.disable('x-powered-by'); if (Config_1.getConfig().ddos) { this.app.use((new ddos(Config_1.getConfig().ddos)).express); } } setStatic() { this.app.get('*.js', (req, res, next) => { Config_1.getConfig().apm && Log.getApm().setTransactionName('GET ' + Url_1.processUrl(req.url), 'static'); if (fs.existsSync(path.resolve(Config_1.getConfig().publicDir, Url_1.processUrl(req.url)) + '.gz')) { req.url = req.url + '.gz'; res.set('Content-Type', 'text/javascript'); res.set('Content-Encoding', 'gzip'); } next(); }); this.app.get('*.css', (req, res, next) => { Config_1.getConfig().apm && Log.getApm().setTransactionName('GET ' + Url_1.processUrl(req.url), 'static'); if (fs.existsSync(path.resolve(Config_1.getConfig().publicDir, Url_1.processUrl(req.url)) + '.gz')) { req.url = req.url + '.gz'; res.set('Content-Type', 'text/css'); res.set('Content-Encoding', 'gzip'); } next(); }); this.app.use(express.static(Config_1.getConfig().publicDir)); this.app.use('/uploads', express.static(Config_1.getConfig().uploadDir)); } setLogger() { this.app.all('/*', (req, res, next) => { Log.logInfo({ message: 'request', method: req.method, path: req.path, url: req.url, hostname: req.hostname, headers: req.headers, ip: req.ip, body: req.body }); next(); }); } setSubscription() { this.subscriptionManager = new Query.SubscriptionManager(); this.subscriptionManager.init(); } setLogError() { this.app.use((error, req, res, next) => { if (error.status) res.status(error.status); else res.status(501); res.json(Error_1.parseAndLogError(error, 'server', req, res)); }); } setRender() { Translation.getLanguages().forEach(language => { this.app.get('/' + language + '/*', (req, res, next) => { Config_1.getConfig().apm && Log.getApm().setTransactionName('GET ' + Url_1.processUrl(req.baseUrl), 'render'); return Render_1.Render(req, res, next, language); }); }); this.app.get('/*', (req, res, next) => { Config_1.getConfig().apm && Log.getApm().setTransactionName('GET ' + Url_1.processUrl(req.baseUrl), 'render'); return Render_1.Render(req, res, next); }); } setFileUpload() { let storage; if (Config_1.getConfig().tempUploadDir) { storage = multer.diskStorage({ destination: (req, file, callback) => { callback(null, path.resolve(Config_1.getConfig().tempUploadDir)); }, filename: (req, file, callback) => { callback(null, file.fieldname + '-' + Date.now() + path.extname(file.originalname)); } }); } else { storage = multer.memoryStorage(); } let upload = multer({ storage, limits: { fileSize: Config_1.getConfig().maxFileSize * 1000000 } }).any(); this.app.post('/*', (req, res, next) => { Config_1.getConfig().apm && Log.getApm().setTransactionName('POST ' + Url_1.processUrl(req.baseUrl), 'upload'); upload(req, res, err => { var a = req; if (err) { res.error = err.message; } next(); }); }); } setWebHook() { Hooks.getWebHooks().forEach(webHook => { this.app.post('/wh/' + webHook.path, (req, res, next) => { Config_1.getConfig().apm && Log.getApm().setTransactionName('POST ' + Url_1.processUrl(req.baseUrl), 'webhook'); WebHook.hook(webHook, req, res, next); }); }); } initGraphQL() { Query.getSchema(); Query.getSubscriptionSchema(); } async setGraphQL() { this.initGraphQL(); this.app.use('/graphql', bodyParser.json(), async (req, res, next) => { Config_1.getConfig().apm && Log.getApm().setTransactionName(req.method + ' ' + Url_1.processUrl(req.baseUrl), 'graphql'); let context = { files: req.files, language: Translation.getLanguage(), quotaLimit: Config_1.getConfig().quotaLimit || 0, quota: 0 }; if (req.body.operations) { req.body = JSON.parse(req.body.operations); } for (let hook of Hooks.getHooksGraphQL()) { await hook(req, context); } Translation_1.setLanguageContext(context); if (req.headers.language) { context.language = req.headers.language; context.trans = (query, ...args) => Translation.trans(context.language, query, ...args); } graphqlHTTP.graphqlExpress({ schema: Query.getSchema(), context, formatError: error => Error_1.parseAndLogError(error, 'graphql', req, res), debug: false, })(req, res, next); }); Config_1.getConfig().graphiql && this.app.get('/graphiql', graphqlHTTP.graphiqlExpress({ endpointURL: '/graphql' })); this.websocketServer = http.createServer(this.app); await new Promise(r => { if (Config_1.getConfig().seaportHost && Config_1.getConfig().seaportPort) { var ports = seaport.connect(Config_1.getConfig().seaportHost, Config_1.getConfig().seaportPort); this.websocketServer.listen(ports.register(Config_1.getConfig().seaportWSName || "ServerWS"), () => { Log.logInfo(`Websocket Server is connected to seaport as "${Config_1.getConfig().seaportWSName || "ServerWS"}" on ${Config_1.getConfig().seaportHost}:${Config_1.getConfig().seaportPort}`); this.subscriptionsServer = this.makeSubscriptionServer(this.websocketServer); r(); }); } else { this.websocketServer.listen(Config_1.getConfig().portWS, () => { Log.logInfo(`Websocket Server is listening on port ${Config_1.getConfig().portWS}`); this.subscriptionsServer = this.makeSubscriptionServer(this.websocketServer); r(); }); } }); } makeSubscriptionServer(websocketServer) { return new subscriptionServer.SubscriptionServer({ schema: Query.getSubscriptionSchema(), execute: graphql.execute, subscribe: graphql.subscribe, onConnect: async (connectionParams, webSocket, connectionContext) => { for (let hook of Hooks.getHooksWSonConnect()) { await hook(connectionParams, webSocket, connectionContext); } if (connectionParams.language) connectionContext.socket.upgradeReq.headers.language = connectionParams.language; }, onOperation: async (message, params, webSocket) => { if (!params.context) params.context = {}; params.context.language = Translation.getLanguage(); for (let hook of Hooks.getHooksWSonMessage()) { await hook(message, params, webSocket); } if (webSocket.upgradeReq.headers.language) params.context.language = webSocket.upgradeReq.headers.language; Translation_1.setLanguageContext(params.context); return params; }, onDisconnect: async (webSocket) => { for (let hook of Hooks.getHooksWSonDisconnect()) { await hook(webSocket); } } }, { server: websocketServer }); } async run() { this.server = http.createServer(this.app); await new Promise(r => { if (Config_1.getConfig().seaportHost && Config_1.getConfig().seaportPort) { Log.logInfo(`Server is connected to seaport as "${Config_1.getConfig().seaportName || "Server"}" on ${Config_1.getConfig().seaportHost}:${Config_1.getConfig().seaportPort}`); var ports = seaport.connect(Config_1.getConfig().seaportHost, Config_1.getConfig().seaportPort); this.server.listen(ports.register(Config_1.getConfig().seaportName || "Server")); for (let hook of Hooks.getHooksAfterServerStart()) { hook(); } r(); } else { this.server.listen(this.app.get('port'), () => { Log.logInfo('Server is listening on port ' + this.app.get('port')); for (let hook of Hooks.getHooksAfterServerStart()) { hook(); } r(); // TODO: Make an example in hooks // if (process.env.NODE_ENV == 'development') fetch('http://localhost:3001/__browser_sync__?method=reload&args=index.js'); }); } }); } } exports.Server = Server; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiU2VydmVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL1NlcnZlci9TZXJ2ZXIudHN4Il0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBQUEsbUNBQW1DO0FBQ25DLDBDQUEwQztBQUMxQyw2QkFBNkI7QUFDN0IsOENBQThDO0FBQzlDLGlDQUFpQztBQUNqQyxxREFBcUQ7QUFDckQsbUNBQW1DO0FBQ25DLGlFQUFpRTtBQUNqRSxpQ0FBaUM7QUFDakMseUJBQXlCO0FBQ3pCLDZCQUE2QjtBQUM3QiwyQ0FBMkM7QUFDM0MsbUNBQW1DO0FBQ25DLE1BQU0sSUFBSSxHQUFHLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQztBQUU3Qiw4Q0FBOEM7QUFDOUMsc0RBQXNEO0FBQ3RELDBDQUEwQztBQUMxQyxzQ0FBc0M7QUFDdEMsOENBQThDO0FBQzlDLCtDQUErQztBQUMvQyw2Q0FBMEM7QUFDMUMsdUNBQStDO0FBQy9DLG1DQUF1QztBQUN2QyxtREFBdUQ7QUFFdkQ7SUFPUyxLQUFLLENBQUMsS0FBSztRQUNoQixNQUFNLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUNsQixNQUFNLElBQUksQ0FBQyxRQUFRLEVBQUUsQ0FBQztRQUN0QixNQUFNLElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQztRQUN2QixNQUFNLElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQztRQUN2QixNQUFNLElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQztRQUN2QixNQUFNLElBQUksQ0FBQyxhQUFhLEVBQUUsQ0FBQztRQUMzQixNQUFNLElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQztRQUN4QixNQUFNLElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQztRQUN4QixNQUFNLElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQztRQUN2QixNQUFNLElBQUksQ0FBQyxlQUFlLEVBQUUsQ0FBQztRQUM3QixNQUFNLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQztRQUN6QixNQUFNLElBQUksQ0FB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