UNPKG

@gameye/sdk

Version:
114 lines 4.17 kB
import * as http from "http"; import * as Koa from "koa"; import * as route from "koa-route"; export class ApiTestServer { constructor(config = {}) { this.koaServer = new Koa(); this.httpServer = http.createServer(); this.socketPool = new Set(); this.patchListenerPool = new Set(); this.config = Object.freeze(Object.assign({}, ApiTestServer.defaultConfig, config)); this.initializeHttpServer(); this.initializeMiddleware(); } static async create(config = {}) { const instance = new this(config); await instance.initialize(); return instance; } getEndpoint() { const address = this.httpServer.address(); if (!address) throw new Error("no address!"); if (typeof address === "string") return address; return `http://localhost:${address.port}`; } emitPatches(patches) { const { patchListenerPool } = this; patchListenerPool.forEach(listener => listener(patches)); } async destroy() { const { httpServer, socketPool } = this; await new Promise(resolve => { const maybeResolve = () => { if (socketPool.size === 0) resolve(); }; socketPool.forEach(socket => { socket.once("close", maybeResolve); socket.destroy(); }); maybeResolve(); }); await new Promise((resolve, reject) => { httpServer.close((err) => { if (err) reject(err); else resolve(); }); }); } initializeMiddleware() { const { token, keepAliveInterval } = this.config; const { koaServer } = this; koaServer.use((context, next) => { if (context.request.header.authorization !== `Bearer ${token}`) { return context.throw(403); } return next(); }); koaServer.use(route.post("/action/*", context => { context.status = 204; })); koaServer.use(route.get("/fetch/*", async (context) => { switch (context.request.accepts("application/json", "application/x-ndjson")) { case "application/json": { context.type = "application/json"; context.status = 200; context.body = {}; break; } case "application/x-ndjson": { const { req, res } = context; context.type = "application/x-ndjson"; context.status = 200; context.flushHeaders(); const patchListener = (patches) => { res.write(JSON.stringify(patches)); res.write("\n"); }; this.patchListenerPool.add(patchListener); const keepAliveIntervalHandle = setInterval(() => { res.write("\n"); }, keepAliveInterval); await new Promise(resolve => { req.on("close", resolve); }); clearInterval(keepAliveIntervalHandle); this.patchListenerPool.delete(patchListener); await new Promise(resolve => res.end(resolve)); break; } } })); } initializeHttpServer() { const { httpServer, koaServer, socketPool } = this; httpServer.on("request", koaServer.callback()); httpServer.on("connection", socket => { socketPool.add(socket); socket.once("close", () => socketPool.delete(socket)); }); } async initialize() { const { httpServer } = this; await new Promise(resolve => httpServer.listen({ port: 0 }, resolve)); } } ApiTestServer.defaultConfig = Object.freeze({ token: "super-secret", keepAliveInterval: 1300, }); //# sourceMappingURL=api.js.map