Server.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. "use strict";
  2. var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
  3. if (k2 === undefined) k2 = k;
  4. var desc = Object.getOwnPropertyDescriptor(m, k);
  5. if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
  6. desc = { enumerable: true, get: function() { return m[k]; } };
  7. }
  8. Object.defineProperty(o, k2, desc);
  9. }) : (function(o, m, k, k2) {
  10. if (k2 === undefined) k2 = k;
  11. o[k2] = m[k];
  12. }));
  13. var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
  14. Object.defineProperty(o, "default", { enumerable: true, value: v });
  15. }) : function(o, v) {
  16. o["default"] = v;
  17. });
  18. var __importStar = (this && this.__importStar) || (function () {
  19. var ownKeys = function(o) {
  20. ownKeys = Object.getOwnPropertyNames || function (o) {
  21. var ar = [];
  22. for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
  23. return ar;
  24. };
  25. return ownKeys(o);
  26. };
  27. return function (mod) {
  28. if (mod && mod.__esModule) return mod;
  29. var result = {};
  30. if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
  31. __setModuleDefault(result, mod);
  32. return result;
  33. };
  34. })();
  35. var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
  36. function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
  37. return new (P || (P = Promise))(function (resolve, reject) {
  38. function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
  39. function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
  40. function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
  41. step((generator = generator.apply(thisArg, _arguments || [])).next());
  42. });
  43. };
  44. var __importDefault = (this && this.__importDefault) || function (mod) {
  45. return (mod && mod.__esModule) ? mod : { "default": mod };
  46. };
  47. Object.defineProperty(exports, "__esModule", { value: true });
  48. exports.Server = void 0;
  49. const express_1 = __importDefault(require("express"));
  50. const http_1 = require("../base/http");
  51. const exceptions_1 = require("../base/exceptions");
  52. const exceptions_2 = require("../base/exceptions");
  53. const logger_1 = require("../base/logger");
  54. const i18n_1 = require("../base/i18n");
  55. const path_1 = __importDefault(require("path"));
  56. const fs_1 = __importDefault(require("fs"));
  57. const http_2 = __importDefault(require("http"));
  58. const ws_1 = require("ws");
  59. const exceptions_3 = require("../base/exceptions");
  60. const exceptions_4 = require("../base/exceptions");
  61. const exceptions_5 = require("../base/exceptions");
  62. const websocket_1 = require("../base/websocket");
  63. /** @sealed */
  64. class Server {
  65. constructor(properties) {
  66. var _a, _b, _c, _d, _e, _f, _g;
  67. this.instance = (0, express_1.default)();
  68. this.httpServer = http_2.default.createServer(this.instance);
  69. this.port = properties.port;
  70. this.host = properties.host || `http://localhost:${this.port}`;
  71. this.i18n = i18n_1.i18nLoader.getInstance();
  72. if (properties.locale)
  73. this.i18n.setLocale(properties.locale);
  74. this.logger = new logger_1.Logger();
  75. this.httpHandlers = {};
  76. this.wsHandlers = properties.wsHandlers || {};
  77. this.wsServers = {};
  78. this.i18nPath = properties.i18nPath;
  79. this.middlewaresPath = properties.middlewaresPath;
  80. this.routesPath = properties.routesPath;
  81. this.viewEngine = properties.viewEngine;
  82. this.viewsPath = properties.viewsPath;
  83. this.options = properties.options;
  84. if (properties.swagger) {
  85. this.swaggerDocsPath = (_a = properties.swagger) === null || _a === void 0 ? void 0 : _a.docsPath;
  86. this.swaggerTitle = ((_b = properties.swagger) === null || _b === void 0 ? void 0 : _b.title) || 'API Documentation';
  87. this.swaggerDescription = ((_c = properties.swagger) === null || _c === void 0 ? void 0 : _c.description) || 'API Documentation';
  88. this.swaggerApiVersion = ((_d = properties.swagger) === null || _d === void 0 ? void 0 : _d.version) || '1.0.0';
  89. this.swaggerRoute = ((_e = properties.swagger) === null || _e === void 0 ? void 0 : _e.route) || '/api-docs';
  90. this.swaggerComponents = (_f = properties.swagger) === null || _f === void 0 ? void 0 : _f.components;
  91. this.swaggerSecurity = (_g = properties.swagger) === null || _g === void 0 ? void 0 : _g.security;
  92. }
  93. this.initialized = false;
  94. }
  95. init() {
  96. return __awaiter(this, void 0, void 0, function* () {
  97. if (this.viewEngine)
  98. this.instance.set('view engine', this.viewEngine);
  99. if (this.viewsPath)
  100. this.instance.set('views', this.viewsPath);
  101. this.i18n.load(path_1.default.resolve(__dirname, Server.i18nDefaultPath));
  102. yield this.registerMiddlewares(path_1.default.resolve(__dirname, Server.defaultMiddlewaresPath));
  103. yield this.registerRoutes(path_1.default.resolve(__dirname, Server.defaultRoutesPath));
  104. yield this.postInit();
  105. this.initialized = true;
  106. return this;
  107. });
  108. }
  109. postInit() {
  110. return __awaiter(this, void 0, void 0, function* () {
  111. if (this.i18nPath)
  112. this.i18n.load(this.i18nPath);
  113. if (this.middlewaresPath)
  114. yield this.registerMiddlewares(this.middlewaresPath);
  115. if (this.routesPath)
  116. yield this.registerRoutes(this.routesPath);
  117. if (this.swaggerDocsPath)
  118. fs_1.default.writeFileSync(this.swaggerDocsPath, '');
  119. if (Object.keys(this.wsHandlers).length > 0) {
  120. this.registerWsServers();
  121. this.applyWsHandlers();
  122. }
  123. });
  124. }
  125. processHttpHandlers() {
  126. const handlers = [];
  127. for (const key in this.httpHandlers)
  128. handlers.push(this.httpHandlers[key]);
  129. handlers.sort((a, b) => a.getOrder() - b.getOrder());
  130. for (const handler of handlers) {
  131. if (handler instanceof http_1.Middleware)
  132. this.addMiddleware(handler);
  133. else if (handler instanceof http_1.Route)
  134. this.addRoute(handler);
  135. }
  136. }
  137. addMiddleware(middleware) {
  138. if (middleware.getRoute() != null)
  139. this.instance.use(middleware.getRoute(), middleware.getAction());
  140. else
  141. this.instance.use(middleware.getAction());
  142. return this;
  143. }
  144. addRoute(route) {
  145. if (route.getRoute() == null)
  146. throw new exceptions_1.RouteNotSetException();
  147. switch (route.getMethod()) {
  148. case http_1.HttpMethod.GET:
  149. return this.get(route);
  150. case http_1.HttpMethod.POST:
  151. return this.post(route);
  152. default:
  153. throw new exceptions_2.IncorrectMethodException();
  154. }
  155. }
  156. registerRoutesDocumentation() {
  157. if (!this.swaggerDocsPath)
  158. return this;
  159. for (const routeName in this.httpHandlers) {
  160. const route = this.httpHandlers[routeName];
  161. if (!(route instanceof http_1.Route))
  162. continue;
  163. if (route.getRoute() == null)
  164. throw new exceptions_1.RouteNotSetException();
  165. if (![http_1.HttpMethod.GET, http_1.HttpMethod.POST].includes(route.getMethod()))
  166. throw new exceptions_2.IncorrectMethodException();
  167. const docs = route.getDocumentation();
  168. if (docs.length > 0) {
  169. fs_1.default.appendFileSync(this.swaggerDocsPath, `${docs}\n`);
  170. this.logInfo((0, i18n_1.$$)('org.crazydoctor.expressts.swagger.routeGenerated', { route: route.getRoute() }));
  171. }
  172. }
  173. return this;
  174. }
  175. registerWsServers() {
  176. for (const url of Object.keys(this.wsHandlers)) {
  177. const wsServer = this.wsServers[url] = new ws_1.Server({ noServer: true });
  178. const wsHandler = this.wsHandlers[url];
  179. wsServer.on(websocket_1.WebSocketHandler.Event.CONNECTION, (ws) => {
  180. wsHandler.onConnect(ws);
  181. ws.on(websocket_1.WebSocketHandler.Event.MESSAGE, wsHandler.onMessage);
  182. ws.on(websocket_1.WebSocketHandler.Event.ERROR, wsHandler.onError);
  183. ws.on(websocket_1.WebSocketHandler.Event.CLOSE, wsHandler.onClose);
  184. });
  185. }
  186. return this;
  187. }
  188. applyWsHandlers() {
  189. this.httpServer.on('upgrade', (request, socket, head) => {
  190. var _a;
  191. const url = (_a = request.url) === null || _a === void 0 ? void 0 : _a.split('?')[0];
  192. if (url && this.wsHandlers[url] && this.wsServers[url]) {
  193. const wsServer = this.wsServers[url];
  194. wsServer.handleUpgrade(request, socket, head, (ws) => {
  195. wsServer.emit(websocket_1.WebSocketHandler.Event.CONNECTION, ws, request);
  196. });
  197. }
  198. else {
  199. socket.destroy();
  200. }
  201. });
  202. return this;
  203. }
  204. getWsConnections(url) {
  205. const wsServer = this.wsServers[url];
  206. return wsServer ? wsServer.clients : null;
  207. }
  208. logInfo(message) {
  209. this.logger.getLogger().info(message);
  210. }
  211. logError(message) {
  212. this.logger.getLogger().error(message);
  213. }
  214. logWarn(message) {
  215. this.logger.getLogger().warn(message);
  216. }
  217. log(message) {
  218. switch (message.type) {
  219. case logger_1.MessageTypes.WARNING:
  220. return this.logWarn(message.text);
  221. case logger_1.MessageTypes.ERROR:
  222. return this.logError(message.text);
  223. default:
  224. return this.logInfo(message.text);
  225. }
  226. }
  227. get(route) {
  228. this.instance.get(route.getRoute(), route.getAction());
  229. return this;
  230. }
  231. post(route) {
  232. this.instance.post(route.getRoute(), route.getAction());
  233. return this;
  234. }
  235. registerRoutes(dir) {
  236. return __awaiter(this, void 0, void 0, function* () {
  237. const files = fs_1.default.readdirSync(dir, { recursive: true, encoding: 'utf8' });
  238. for (const file of files) {
  239. if (/\.js$/.test(file)) {
  240. const { default: RouteClass } = yield Promise.resolve(`${path_1.default.join(dir, file)}`).then(s => __importStar(require(s)));
  241. if (RouteClass.prototype instanceof http_1.Route) {
  242. this.httpHandlers[RouteClass.name] = new RouteClass(this);
  243. }
  244. else
  245. throw new exceptions_4.InvalidRouteException(file);
  246. }
  247. }
  248. return this;
  249. });
  250. }
  251. registerMiddlewares(dir) {
  252. return __awaiter(this, void 0, void 0, function* () {
  253. const files = fs_1.default.readdirSync(dir, { recursive: true, encoding: 'utf8' });
  254. for (const file of files) {
  255. if (/\.js$/.test(file)) {
  256. const { default: MiddlewareClass } = yield Promise.resolve(`${path_1.default.join(dir, file)}`).then(s => __importStar(require(s)));
  257. if (MiddlewareClass.prototype instanceof http_1.Middleware) {
  258. this.httpHandlers[MiddlewareClass.name] = new MiddlewareClass(this);
  259. }
  260. else
  261. throw new exceptions_3.InvalidMiddlewareException(file);
  262. }
  263. }
  264. return this;
  265. });
  266. }
  267. getLogger() {
  268. return this.logger;
  269. }
  270. i18nLoad(path) {
  271. this.i18n.load(path);
  272. return this;
  273. }
  274. getHost() {
  275. return this.host;
  276. }
  277. getOption(key) {
  278. return this.options ? this.options[key] || null : null;
  279. }
  280. start(callback) {
  281. if (!this.initialized)
  282. throw new exceptions_5.ServerNotInitializedException();
  283. this.registerRoutesDocumentation();
  284. this.processHttpHandlers();
  285. const cb = () => {
  286. this.logInfo((0, i18n_1.$$)('org.crazydoctor.expressts.start', { 'port': this.port }));
  287. if (callback)
  288. callback();
  289. };
  290. this.httpServer.listen(this.port, cb);
  291. }
  292. }
  293. exports.Server = Server;
  294. Server.i18nDefaultPath = '../resources/i18n.json';
  295. Server.defaultMiddlewaresPath = '../middlewares';
  296. Server.defaultRoutesPath = '../routes';
  297. //# sourceMappingURL=Server.js.map