UNPKG

@furystack/rest-service

Version:

Repository implementation for FuryStack

76 lines 3.44 kB
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var ServerManager_1; import { Injectable } from '@furystack/inject'; import { EventHub } from '@furystack/utils'; import { createServer } from 'http'; import { Lock } from 'semaphore-async-await'; let ServerManager = class ServerManager extends EventHub { static { ServerManager_1 = this; } static DEFAULT_HOST = 'localhost'; servers = new Map(); openedSockets = new Set(); listenLock = new Lock(); getHostUrl = (options) => `http://${options.hostName || ServerManager_1.DEFAULT_HOST}:${options.port}`; onConnection = (socket) => { this.openedSockets.add(socket); socket.once('close', () => this.openedSockets.delete(socket)); }; async [Symbol.asyncDispose]() { try { await this.listenLock.waitFor(5000); } finally { this.openedSockets.forEach((s) => s.destroy()); await Promise.allSettled([...this.servers.values()].map((s) => new Promise((resolve, reject) => { s.server.close((err) => (err ? reject(err) : resolve())); s.server.off('connection', this.onConnection); }))); this.servers.clear(); this.listenLock.release(); super[Symbol.dispose]?.(); } } async getOrCreate(options) { const url = this.getHostUrl(options); if (!this.servers.has(url)) { await this.listenLock.acquire(); try { if (!this.servers.has(url)) { await new Promise((resolve, reject) => { const apis = []; const server = createServer((req, res) => { const apiMatch = apis.find((api) => api.shouldExec({ req, res })); if (apiMatch) { apiMatch.onRequest({ req, res }).catch((error) => { this.emit('onRequestFailed', [error, req, res]); }); } else { res.destroy(); } }); server.on('connection', this.onConnection); server.on('listening', () => resolve()); server.on('error', (err) => reject(err)); server.listen(options.port, options.hostName); this.servers.set(url, { server, apis }); }); } } finally { this.listenLock.release(); } } return this.servers.get(url); } }; ServerManager = ServerManager_1 = __decorate([ Injectable({ lifetime: 'singleton' }) ], ServerManager); export { ServerManager }; //# sourceMappingURL=server-manager.js.map