spiegel-keyman/developer/server/src/index.ts
2022-01-28 15:48:10 +11:00

126 lines
3.9 KiB
TypeScript

import { environment } from './environment';
const Sentry = require("@sentry/node");
Sentry.init({
dsn: 'https://39b25a09410349a58fe12aaf721565af@o1005580.ingest.sentry.io/5983519', // Keyman Developer
environment: environment.versionEnvironment,
release: environment.versionWithTag
});
import express = require('express');
import ws = require('ws');
import os = require('os');
import multer = require('multer');
import fs = require('fs');
import setupRoutes from './routes';
import { configuration } from './config';
import tray from './tray';
import chalk = require('chalk');
const options = {
ngrokLog: false, // Set this to true if you need to see ngrok logs in the console
};
/* Lock file - report on PID and prevent multiple instances cleanly */
console.log(`Starting Keyman Developer Server ${environment.versionWithTag}, listening on port ${configuration.port}.`);
// This triggers the exit event for Ctrl+C which allows us to cleanup
// consistently
process.on('SIGINT', ()=>{process.exit(0)});
if(fs.existsSync(configuration.lockFilename)) {
// Attempt connection to existing port
// If that fails, we'll assume the previous process died and delete the lockfile.
}
// TODO: flock with fs-ext
let lockFileDescriptor = fs.openSync(configuration.lockFilename, 'w');
fs.writeFileSync(configuration.pidFilename, process.pid.toString());
fs.writeFileSync(lockFileDescriptor, process.pid.toString());
process.on('exit', () => {
if(fs.existsSync(configuration.pidFilename)) {
fs.unlinkSync(configuration.pidFilename);
}
if(lockFileDescriptor) {
fs.closeSync(lockFileDescriptor);
lockFileDescriptor = null;
fs.unlinkSync(configuration.lockFilename);
}
});
/* Server Setup */
const app = express();
const upload = multer({ storage: multer.memoryStorage(), limits: { fileSize: 1024*1024*10 /*10MB*/ } });
/* Websockets */
const wsServer = new ws.Server({ noServer: true });
wsServer.on('connection', socket => {
socket.on('message', (message) => {
console.debug('wsServer.socket.onmessage: '+message.toString());
if(message.toString() == 'ping')
socket.send('pong');
});
socket.send('refresh');
});
/* Setup routes */
setupRoutes(app, upload, wsServer, environment);
/* Start the server */
const server = app.listen(configuration.port);
server.on('upgrade', (request, socket, head) => {
wsServer.handleUpgrade(request, socket, head, socket => {
wsServer.emit('connection', socket, request);
});
});
/* Launch ngrok if enabled */
configuration.ngrokEndpoint = '';
if(configuration.useNgrok && os.platform() == 'win32' && fs.existsSync(configuration.ngrokBinPath)) {
const ngrok = require('ngrok');
(async function() {
configuration.ngrokEndpoint = await ngrok.connect({
proto: 'http',
bind_tls: true,
addr: configuration.port,
authtoken: configuration.ngrokToken,
region: configuration.ngrokRegion,
binPath: () => configuration.ngrokBinPath,
onLogEvent: (msg: string) => {
if(options.ngrokLog) {
console.log(chalk.cyan(('\n'+msg).split('\n').join('\n[ngrok] ').trim()));
}
},
onStatusChange: (state: string) => {
if(state == 'connected') {
setTimeout(async () => {
const api = ngrok.getApi();
const tunnels = await api.listTunnels();
configuration.ngrokEndpoint = tunnels.tunnels[0]?.public_url ?? '';
console.log(chalk.blueBright('ngrok tunnel established at %s'), configuration.ngrokEndpoint);
}, 1000);
} else if(state == 'closed') {
configuration.ngrokEndpoint = '';
console.log(chalk.blueBright('ngrok tunnel closed'));
}
}
});
console.log(chalk.blueBright('ngrok tunnel initially established at %s'), configuration.ngrokEndpoint);
tray.start(configuration.port, configuration.ngrokEndpoint);
})();
}
else {
/* Load the tray icon */
tray.start(configuration.port, configuration.ngrokEndpoint);
}