@colyseus/monitor 0.17.8 → 0.18.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/ext/Room.cjs +1 -2
- package/build/ext/Room.cjs.map +2 -2
- package/build/ext/Room.mjs +1 -2
- package/build/ext/Room.mjs.map +2 -2
- package/build/index.cjs +129 -7
- package/build/index.cjs.map +3 -3
- package/build/index.d.ts +9 -4
- package/build/index.mjs +124 -7
- package/build/index.mjs.map +2 -2
- package/build/serve-static.cjs +107 -0
- package/build/serve-static.cjs.map +7 -0
- package/build/serve-static.d.ts +1 -0
- package/build/serve-static.mjs +72 -0
- package/build/serve-static.mjs.map +7 -0
- package/build/static/assets/{index-DsiKUEz6.js → index-CDY0bZlU.js} +2 -2
- package/build/static/assets/{index-DsiKUEz6.js.map → index-CDY0bZlU.js.map} +1 -1
- package/build/static/index.html +1 -1
- package/package.json +7 -4
- package/src-backend/ext/Room.ts +1 -2
- package/src-backend/index.ts +154 -21
- package/src-backend/serve-static.ts +73 -0
- package/build/api.cjs +0 -110
- package/build/api.cjs.map +0 -7
- package/build/api.d.ts +0 -3
- package/build/api.mjs +0 -75
- package/build/api.mjs.map +0 -7
- package/src-backend/api.ts +0 -94
package/build/static/index.html
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
|
7
7
|
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
|
|
8
8
|
<title>Colyseus Stats</title>
|
|
9
|
-
<script type="module" crossorigin src="./assets/index-
|
|
9
|
+
<script type="module" crossorigin src="./assets/index-CDY0bZlU.js"></script>
|
|
10
10
|
<link rel="stylesheet" crossorigin href="./assets/index-C4SPBCkT.css">
|
|
11
11
|
</head>
|
|
12
12
|
<body>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@colyseus/monitor",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.18.1",
|
|
4
4
|
"description": "Web Monitoring Panel for Colyseus",
|
|
5
5
|
"input": "./src/index.ts",
|
|
6
6
|
"main": "./build/index.cjs",
|
|
@@ -61,13 +61,16 @@
|
|
|
61
61
|
"react-dom": "^18.2.0",
|
|
62
62
|
"json-edit-react": "^1.17.0",
|
|
63
63
|
"react-router-dom": "^4.2.2",
|
|
64
|
-
"typescript": "^
|
|
64
|
+
"typescript": "^6.0.3",
|
|
65
65
|
"vite": "^5.0.11"
|
|
66
66
|
},
|
|
67
67
|
"dependencies": {
|
|
68
|
-
"express": ">=4.16.0",
|
|
69
68
|
"node-os-utils": "^2.0.0",
|
|
70
|
-
"
|
|
69
|
+
"zod": "^4.1.12",
|
|
70
|
+
"@colyseus/core": "^0.18.1"
|
|
71
|
+
},
|
|
72
|
+
"publishConfig": {
|
|
73
|
+
"tag": "next"
|
|
71
74
|
},
|
|
72
75
|
"scripts": {
|
|
73
76
|
"start": "vite",
|
package/src-backend/ext/Room.ts
CHANGED
|
@@ -7,8 +7,7 @@ function getStateSize(room) {
|
|
|
7
7
|
// TODO: `Serializer<T>` should provide a method for this (e.g. `serializer.hasState()`)
|
|
8
8
|
const hasState = (
|
|
9
9
|
room._serializer.encoder || // schema v3
|
|
10
|
-
room._serializer.state
|
|
11
|
-
room._serializer.previousState // legacy-fossil-delta
|
|
10
|
+
room._serializer.state // schema v2
|
|
12
11
|
);
|
|
13
12
|
const fullState = hasState && room._serializer.getFullState();
|
|
14
13
|
return fullState && (fullState.byteLength || fullState.length) || 0;
|
package/src-backend/index.ts
CHANGED
|
@@ -1,31 +1,164 @@
|
|
|
1
|
-
import
|
|
1
|
+
import fs from 'fs/promises';
|
|
2
2
|
import path from 'path';
|
|
3
|
-
|
|
4
|
-
// required for ESM support. (esbuild uses it)
|
|
5
3
|
import { fileURLToPath } from 'url';
|
|
4
|
+
import { z } from 'zod';
|
|
5
|
+
import { createEndpoint, dualModeEndpoints, matchMaker, type Endpoint } from '@colyseus/core';
|
|
6
|
+
import { OSUtils } from 'node-os-utils';
|
|
6
7
|
|
|
7
|
-
import {
|
|
8
|
+
import { serveStatic } from './serve-static.js';
|
|
8
9
|
import './ext/Room.js';
|
|
9
10
|
|
|
10
|
-
const
|
|
11
|
+
const osutils = new OSUtils();
|
|
12
|
+
const UNAVAILABLE_ROOM_ERROR = "@colyseus/monitor: room $roomId is not available anymore.";
|
|
13
|
+
const SPA_DIST = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..', 'build', 'static');
|
|
11
14
|
|
|
12
15
|
export interface MonitorOptions {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
16
|
+
/** Mount prefix used when spread into `createRouter`. Ignored in express-middleware mode. Defaults to `''`. */
|
|
17
|
+
prefix?: string;
|
|
18
|
+
/** Better-call middleware applied to every monitor endpoint — use for auth gating. */
|
|
19
|
+
use?: any[];
|
|
20
|
+
/** Columns shown in the rooms grid. */
|
|
21
|
+
columns?: Array<
|
|
22
|
+
'roomId' |
|
|
23
|
+
'name' |
|
|
24
|
+
'clients' |
|
|
25
|
+
'maxClients' |
|
|
26
|
+
'locked' |
|
|
27
|
+
'elapsedTime' |
|
|
28
|
+
{ metadata: string } |
|
|
29
|
+
'processId' |
|
|
30
|
+
'publicAddress'
|
|
31
|
+
>;
|
|
24
32
|
}
|
|
25
33
|
|
|
26
|
-
export function monitor
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
34
|
+
export function monitor(opts: MonitorOptions = {}) {
|
|
35
|
+
const prefix = opts.prefix ?? '/monitor';
|
|
36
|
+
const use = opts.use ?? [];
|
|
37
|
+
const columnsOpt = opts.columns;
|
|
38
|
+
|
|
39
|
+
const endpoints: Record<string, Endpoint> = {
|
|
40
|
+
'monitor-api-rooms': createEndpoint(`${prefix}/api`, { method: 'GET', use }, async () => {
|
|
41
|
+
try {
|
|
42
|
+
const rooms: any[] = await matchMaker.query({});
|
|
43
|
+
const columns = columnsOpt ?? ['roomId', 'name', 'clients', 'maxClients', 'locked', 'elapsedTime'];
|
|
44
|
+
|
|
45
|
+
if (!columnsOpt && rooms[0] && rooms[0].publicAddress !== undefined) {
|
|
46
|
+
columns.push('publicAddress');
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
let connections = 0;
|
|
50
|
+
const cpuUsage = await osutils.cpu.usage();
|
|
51
|
+
const cpu = cpuUsage.success ? cpuUsage.data : NaN;
|
|
52
|
+
const memoryInfo = await osutils.memory.info();
|
|
53
|
+
const totalMemMb = memoryInfo.success ? memoryInfo.data.total?.toMB() : NaN;
|
|
54
|
+
const usedMemMb = memoryInfo.success ? memoryInfo.data.used?.toMB() : NaN;
|
|
55
|
+
|
|
56
|
+
return {
|
|
57
|
+
columns,
|
|
58
|
+
rooms: rooms.map((room) => {
|
|
59
|
+
const data = JSON.parse(JSON.stringify(room));
|
|
60
|
+
connections += room.clients;
|
|
61
|
+
data.locked = room.locked || false;
|
|
62
|
+
data.private = room.private;
|
|
63
|
+
data.maxClients = `${room.maxClients}`;
|
|
64
|
+
data.elapsedTime = Date.now() - new Date(room.createdAt).getTime();
|
|
65
|
+
return data;
|
|
66
|
+
}),
|
|
67
|
+
connections,
|
|
68
|
+
cpu,
|
|
69
|
+
memory: { totalMemMb, usedMemMb },
|
|
70
|
+
};
|
|
71
|
+
} catch (e: any) {
|
|
72
|
+
console.error(e.message);
|
|
73
|
+
return new Response(JSON.stringify({ message: e.message }), {
|
|
74
|
+
status: 500,
|
|
75
|
+
headers: { 'content-type': 'application/json' },
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
}),
|
|
79
|
+
|
|
80
|
+
'monitor-api-room': createEndpoint(`${prefix}/api/room`, {
|
|
81
|
+
method: 'GET',
|
|
82
|
+
query: z.object({ roomId: z.string() }),
|
|
83
|
+
use,
|
|
84
|
+
}, async (ctx) => {
|
|
85
|
+
const roomId = ctx.query.roomId;
|
|
86
|
+
try {
|
|
87
|
+
return await matchMaker.remoteRoomCall(roomId, 'getInspectData');
|
|
88
|
+
} catch {
|
|
89
|
+
return new Response(JSON.stringify({ message: UNAVAILABLE_ROOM_ERROR.replace('$roomId', roomId) }), {
|
|
90
|
+
status: 500,
|
|
91
|
+
headers: { 'content-type': 'application/json' },
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
}),
|
|
95
|
+
|
|
96
|
+
'monitor-api-room-call': createEndpoint(`${prefix}/api/room/call`, {
|
|
97
|
+
method: 'GET',
|
|
98
|
+
query: z.object({ roomId: z.string(), method: z.string(), args: z.string() }),
|
|
99
|
+
use,
|
|
100
|
+
}, async (ctx) => {
|
|
101
|
+
const { roomId, method } = ctx.query;
|
|
102
|
+
try {
|
|
103
|
+
const args = JSON.parse(ctx.query.args);
|
|
104
|
+
const data = await matchMaker.remoteRoomCall(roomId, method, args);
|
|
105
|
+
return data ?? {};
|
|
106
|
+
} catch {
|
|
107
|
+
return new Response(JSON.stringify({ message: UNAVAILABLE_ROOM_ERROR.replace('$roomId', roomId) }), {
|
|
108
|
+
status: 500,
|
|
109
|
+
headers: { 'content-type': 'application/json' },
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
}),
|
|
113
|
+
|
|
114
|
+
'monitor-index': createEndpoint(`${prefix}/`, { method: 'GET', use }, async () => {
|
|
115
|
+
return serveStatic(SPA_DIST, '');
|
|
116
|
+
}),
|
|
117
|
+
|
|
118
|
+
'monitor-static': createEndpoint(`${prefix}/**:splat`, { method: 'GET', use }, async (ctx) => {
|
|
119
|
+
return serveStatic(SPA_DIST, (ctx.params as any).splat);
|
|
120
|
+
}),
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
const SPA_DIST_RESOLVED = path.resolve(SPA_DIST);
|
|
124
|
+
|
|
125
|
+
// Express compat — works with either `app.use("/monitor", monitor())` or
|
|
126
|
+
// `app.use("/", monitor())`. Routing decisions use originalUrl (the same
|
|
127
|
+
// string better-call's getRequest uses to build the dispatched Request URL),
|
|
128
|
+
// so the middleware's match check and the actual dispatch always agree.
|
|
129
|
+
return dualModeEndpoints(endpoints, {
|
|
130
|
+
catchAllKey: 'monitor-static',
|
|
131
|
+
buildMiddleware: ({ specificRouter, specificHandler, fullHandler }) => (req, res, next) => {
|
|
132
|
+
if (req.method !== 'GET') { return next(); }
|
|
133
|
+
|
|
134
|
+
const dispatchUrl = ((req as any).originalUrl ?? req.url ?? '').split('?')[0]!;
|
|
135
|
+
|
|
136
|
+
// Bare prefix (`/monitor`) → 301 to canonical `/monitor/`.
|
|
137
|
+
if (prefix && dispatchUrl === prefix) {
|
|
138
|
+
res.writeHead(301, { location: `${prefix}/` });
|
|
139
|
+
res.end();
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
const route = specificRouter.findRoute('GET', dispatchUrl);
|
|
144
|
+
if (route && route.data?.path === dispatchUrl) {
|
|
145
|
+
return specificHandler(req as any, res as any).catch(next);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// Asset request — only delegate if the file exists on disk.
|
|
149
|
+
if (!dispatchUrl.startsWith(prefix)) { return next(); }
|
|
150
|
+
const rel = dispatchUrl.slice(prefix.length).replace(/^\/+/, '');
|
|
151
|
+
if (!rel || rel.includes('..')) { return next(); }
|
|
152
|
+
const filePath = path.resolve(SPA_DIST_RESOLVED, rel);
|
|
153
|
+
if (!filePath.startsWith(SPA_DIST_RESOLVED + path.sep)) { return next(); }
|
|
154
|
+
|
|
155
|
+
fs.stat(filePath).then((stat) => {
|
|
156
|
+
if (stat.isFile()) {
|
|
157
|
+
fullHandler(req as any, res as any).catch(next);
|
|
158
|
+
} else {
|
|
159
|
+
next();
|
|
160
|
+
}
|
|
161
|
+
}).catch(() => next());
|
|
162
|
+
},
|
|
163
|
+
});
|
|
31
164
|
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
// Static-file helper. Duplicated from @colyseus/admin / @colyseus/playground.
|
|
2
|
+
import fs from 'fs/promises';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
|
|
5
|
+
const MIME: Record<string, string> = {
|
|
6
|
+
'.html': 'text/html; charset=utf-8',
|
|
7
|
+
'.js': 'application/javascript; charset=utf-8',
|
|
8
|
+
'.mjs': 'application/javascript; charset=utf-8',
|
|
9
|
+
'.css': 'text/css; charset=utf-8',
|
|
10
|
+
'.json': 'application/json; charset=utf-8',
|
|
11
|
+
'.svg': 'image/svg+xml',
|
|
12
|
+
'.png': 'image/png',
|
|
13
|
+
'.jpg': 'image/jpeg',
|
|
14
|
+
'.jpeg': 'image/jpeg',
|
|
15
|
+
'.gif': 'image/gif',
|
|
16
|
+
'.ico': 'image/x-icon',
|
|
17
|
+
'.woff': 'font/woff',
|
|
18
|
+
'.woff2': 'font/woff2',
|
|
19
|
+
'.ttf': 'font/ttf',
|
|
20
|
+
'.map': 'application/json; charset=utf-8',
|
|
21
|
+
'.txt': 'text/plain; charset=utf-8',
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export async function serveStatic(root: string, relPath: string | undefined): Promise<Response> {
|
|
25
|
+
const safe = sanitize(relPath ?? '');
|
|
26
|
+
const filePath = safe ? path.join(root, safe) : path.join(root, 'index.html');
|
|
27
|
+
|
|
28
|
+
const resolved = path.resolve(filePath);
|
|
29
|
+
const resolvedRoot = path.resolve(root);
|
|
30
|
+
if (!resolved.startsWith(resolvedRoot + path.sep) && resolved !== resolvedRoot) {
|
|
31
|
+
return new Response('forbidden', { status: 403 });
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const data = await tryRead(resolved);
|
|
35
|
+
if (data) { return fileResponse(data, mimeOf(resolved)); }
|
|
36
|
+
|
|
37
|
+
if (!path.extname(safe)) {
|
|
38
|
+
const index = await tryRead(path.join(resolvedRoot, 'index.html'));
|
|
39
|
+
if (index) { return fileResponse(index, 'text/html; charset=utf-8'); }
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return new Response('not found', { status: 404 });
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function sanitize(p: string): string {
|
|
46
|
+
return p.replace(/^\/+/, '').split('/').filter((seg) => seg && seg !== '..' && seg !== '.').join('/');
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function mimeOf(filePath: string): string {
|
|
50
|
+
return MIME[path.extname(filePath).toLowerCase()] ?? 'application/octet-stream';
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
async function tryRead(filePath: string): Promise<Buffer | null> {
|
|
54
|
+
try {
|
|
55
|
+
const stat = await fs.stat(filePath);
|
|
56
|
+
if (!stat.isFile()) { return null; }
|
|
57
|
+
return await fs.readFile(filePath);
|
|
58
|
+
} catch {
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function fileResponse(buf: Buffer, contentType: string): Response {
|
|
64
|
+
return new Response(new Uint8Array(buf) as any, {
|
|
65
|
+
status: 200,
|
|
66
|
+
headers: {
|
|
67
|
+
'content-type': contentType,
|
|
68
|
+
'content-length': String(buf.length),
|
|
69
|
+
'cache-control': 'no-cache',
|
|
70
|
+
'connection': 'close',
|
|
71
|
+
},
|
|
72
|
+
});
|
|
73
|
+
}
|
package/build/api.cjs
DELETED
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
var __create = Object.create;
|
|
2
|
-
var __defProp = Object.defineProperty;
|
|
3
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
6
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
-
var __export = (target, all) => {
|
|
8
|
-
for (var name in all)
|
|
9
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
-
};
|
|
11
|
-
var __copyProps = (to, from, except, desc) => {
|
|
12
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
-
for (let key of __getOwnPropNames(from))
|
|
14
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
-
}
|
|
17
|
-
return to;
|
|
18
|
-
};
|
|
19
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
20
|
-
// If the importer is in node compatibility mode or this is not an ESM
|
|
21
|
-
// file that has been converted to a CommonJS file using a Babel-
|
|
22
|
-
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
23
|
-
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
24
|
-
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
25
|
-
mod
|
|
26
|
-
));
|
|
27
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
28
|
-
|
|
29
|
-
// src-backend/api.ts
|
|
30
|
-
var api_exports = {};
|
|
31
|
-
__export(api_exports, {
|
|
32
|
-
getAPI: () => getAPI
|
|
33
|
-
});
|
|
34
|
-
module.exports = __toCommonJS(api_exports);
|
|
35
|
-
var import_core = require("@colyseus/core");
|
|
36
|
-
var import_express = __toESM(require("express"));
|
|
37
|
-
var import_node_os_utils = require("node-os-utils");
|
|
38
|
-
var osutils = new import_node_os_utils.OSUtils();
|
|
39
|
-
var UNAVAILABLE_ROOM_ERROR = "@colyseus/monitor: room $roomId is not available anymore.";
|
|
40
|
-
function getAPI(opts) {
|
|
41
|
-
const api = import_express.default.Router();
|
|
42
|
-
api.get("/", async (req, res) => {
|
|
43
|
-
var _a, _b;
|
|
44
|
-
try {
|
|
45
|
-
const rooms = await import_core.matchMaker.query({});
|
|
46
|
-
const columns = opts.columns || ["roomId", "name", "clients", "maxClients", "locked", "elapsedTime"];
|
|
47
|
-
if (!opts.columns && rooms[0] && rooms[0].publicAddress !== void 0) {
|
|
48
|
-
columns.push("publicAddress");
|
|
49
|
-
}
|
|
50
|
-
let connections = 0;
|
|
51
|
-
const cpuUsage = await osutils.cpu.usage();
|
|
52
|
-
const cpu = cpuUsage.success ? cpuUsage.data : NaN;
|
|
53
|
-
const memoryInfo = await osutils.memory.info();
|
|
54
|
-
const totalMemMb = memoryInfo.success ? (_a = memoryInfo.data.total) == null ? void 0 : _a.toMB() : NaN;
|
|
55
|
-
const usedMemMb = memoryInfo.success ? (_b = memoryInfo.data.used) == null ? void 0 : _b.toMB() : NaN;
|
|
56
|
-
res.json({
|
|
57
|
-
columns,
|
|
58
|
-
rooms: rooms.map((room) => {
|
|
59
|
-
const data = JSON.parse(JSON.stringify(room));
|
|
60
|
-
connections += room.clients;
|
|
61
|
-
data.locked = room.locked || false;
|
|
62
|
-
data.private = room.private;
|
|
63
|
-
data.maxClients = `${room.maxClients}`;
|
|
64
|
-
data.elapsedTime = Date.now() - new Date(room.createdAt).getTime();
|
|
65
|
-
return data;
|
|
66
|
-
}),
|
|
67
|
-
connections,
|
|
68
|
-
cpu,
|
|
69
|
-
memory: {
|
|
70
|
-
totalMemMb,
|
|
71
|
-
usedMemMb
|
|
72
|
-
}
|
|
73
|
-
});
|
|
74
|
-
} catch (e) {
|
|
75
|
-
const message = e.message;
|
|
76
|
-
console.error(message);
|
|
77
|
-
res.status(500);
|
|
78
|
-
res.json({ message });
|
|
79
|
-
}
|
|
80
|
-
});
|
|
81
|
-
api.get("/room", async (req, res) => {
|
|
82
|
-
const roomId = req.query.roomId;
|
|
83
|
-
try {
|
|
84
|
-
const inspectData = await import_core.matchMaker.remoteRoomCall(roomId, "getInspectData");
|
|
85
|
-
res.json(inspectData);
|
|
86
|
-
} catch (e) {
|
|
87
|
-
const message = UNAVAILABLE_ROOM_ERROR.replace("$roomId", roomId);
|
|
88
|
-
res.status(500);
|
|
89
|
-
res.json({ message });
|
|
90
|
-
}
|
|
91
|
-
});
|
|
92
|
-
api.get("/room/call", async (req, res) => {
|
|
93
|
-
const roomId = req.query.roomId;
|
|
94
|
-
const method = req.query.method;
|
|
95
|
-
const args = JSON.parse(req.query.args);
|
|
96
|
-
try {
|
|
97
|
-
const data = await import_core.matchMaker.remoteRoomCall(roomId, method, args);
|
|
98
|
-
res.json(data != null ? data : {});
|
|
99
|
-
} catch (e) {
|
|
100
|
-
const message = UNAVAILABLE_ROOM_ERROR.replace("$roomId", roomId);
|
|
101
|
-
res.status(500);
|
|
102
|
-
res.json({ message });
|
|
103
|
-
}
|
|
104
|
-
});
|
|
105
|
-
return api;
|
|
106
|
-
}
|
|
107
|
-
// Annotate the CommonJS export names for ESM import in node:
|
|
108
|
-
0 && (module.exports = {
|
|
109
|
-
getAPI
|
|
110
|
-
});
|
package/build/api.cjs.map
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../src-backend/api.ts"],
|
|
4
|
-
"sourcesContent": ["import { matchMaker } from '@colyseus/core';\n\nimport express from 'express';\nimport { OSUtils } from 'node-os-utils';\n\nimport type { MonitorOptions } from './index.js';\n\nconst osutils = new OSUtils();\n\nconst UNAVAILABLE_ROOM_ERROR = \"@colyseus/monitor: room $roomId is not available anymore.\";\n\nexport function getAPI (opts: Partial<MonitorOptions>): express.Router {\n const api = express.Router();\n\n api.get(\"/\", async (req: express.Request, res: express.Response) => {\n try {\n const rooms: any[] = await matchMaker.query({});\n const columns = opts.columns || ['roomId', 'name', 'clients', 'maxClients', 'locked', 'elapsedTime'];\n\n // extend columns to expose \"publicAddress\", if present\n if (!opts.columns && rooms[0] && rooms[0].publicAddress !== undefined) {\n columns.push(\"publicAddress\");\n }\n\n let connections: number = 0;\n\n const cpuUsage = await osutils.cpu.usage();\n const cpu = (cpuUsage.success) ? cpuUsage.data : NaN;\n\n const memoryInfo = await osutils.memory.info();\n const totalMemMb = (memoryInfo.success) ? memoryInfo.data.total?.toMB() : NaN;\n const usedMemMb = (memoryInfo.success) ? memoryInfo.data.used?.toMB() : NaN;\n\n res.json({\n columns,\n rooms: rooms.map(room => {\n const data = JSON.parse(JSON.stringify(room));\n\n connections += room.clients;\n\n // additional data\n data.locked = room.locked || false;\n data.private = room.private;\n\n data.maxClients = `${room.maxClients}`;\n\n data.elapsedTime = Date.now() - new Date(room.createdAt).getTime();\n return data;\n }),\n\n connections,\n cpu,\n memory: {\n totalMemMb,\n usedMemMb \n },\n });\n } catch (e: any) {\n const message = e.message;\n console.error(message);\n res.status(500);\n res.json({ message });\n }\n });\n\n api.get(\"/room\", async (req: express.Request, res: express.Response) => {\n const roomId = req.query.roomId as string;\n try {\n const inspectData = await matchMaker.remoteRoomCall(roomId, \"getInspectData\");\n res.json(inspectData);\n } catch (e) {\n const message = UNAVAILABLE_ROOM_ERROR.replace(\"$roomId\", roomId);\n res.status(500);\n res.json({ message });\n }\n });\n\n api.get(\"/room/call\", async (req: express.Request, res: express.Response) => {\n const roomId = req.query.roomId as string;\n const method = req.query.method as string;\n const args = JSON.parse(req.query.args as string);\n\n try {\n const data = await matchMaker.remoteRoomCall(roomId, method, args);\n res.json(data ?? {});\n } catch (e) {\n const message = UNAVAILABLE_ROOM_ERROR.replace(\"$roomId\", roomId);\n res.status(500);\n res.json({ message });\n }\n });\n\n return api;\n}\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,kBAA2B;AAE3B,qBAAoB;AACpB,2BAAwB;AAIxB,IAAM,UAAU,IAAI,6BAAQ;AAE5B,IAAM,yBAAyB;AAExB,SAAS,OAAQ,MAA+C;AACnE,QAAM,MAAM,eAAAA,QAAQ,OAAO;AAE3B,MAAI,IAAI,KAAK,OAAO,KAAsB,QAA0B;AAdxE;AAeQ,QAAI;AACA,YAAM,QAAe,MAAM,uBAAW,MAAM,CAAC,CAAC;AAC9C,YAAM,UAAU,KAAK,WAAW,CAAC,UAAU,QAAQ,WAAW,cAAc,UAAU,aAAa;AAGnG,UAAI,CAAC,KAAK,WAAW,MAAM,CAAC,KAAK,MAAM,CAAC,EAAE,kBAAkB,QAAW;AACnE,gBAAQ,KAAK,eAAe;AAAA,MAChC;AAEA,UAAI,cAAsB;AAE1B,YAAM,WAAW,MAAM,QAAQ,IAAI,MAAM;AACzC,YAAM,MAAO,SAAS,UAAW,SAAS,OAAO;AAEjD,YAAM,aAAa,MAAM,QAAQ,OAAO,KAAK;AAC7C,YAAM,aAAc,WAAW,WAAW,gBAAW,KAAK,UAAhB,mBAAuB,SAAS;AAC1E,YAAM,YAAa,WAAW,WAAW,gBAAW,KAAK,SAAhB,mBAAsB,SAAS;AAExE,UAAI,KAAK;AAAA,QACL;AAAA,QACA,OAAO,MAAM,IAAI,UAAQ;AACrB,gBAAM,OAAO,KAAK,MAAM,KAAK,UAAU,IAAI,CAAC;AAE5C,yBAAe,KAAK;AAGpB,eAAK,SAAS,KAAK,UAAU;AAC7B,eAAK,UAAU,KAAK;AAEpB,eAAK,aAAa,GAAG,KAAK,UAAU;AAEpC,eAAK,cAAc,KAAK,IAAI,IAAI,IAAI,KAAK,KAAK,SAAS,EAAE,QAAQ;AACjE,iBAAO;AAAA,QACX,CAAC;AAAA,QAED;AAAA,QACA;AAAA,QACA,QAAQ;AAAA,UACJ;AAAA,UACA;AAAA,QACJ;AAAA,MACJ,CAAC;AAAA,IACL,SAAS,GAAQ;AACb,YAAM,UAAU,EAAE;AAClB,cAAQ,MAAM,OAAO;AACrB,UAAI,OAAO,GAAG;AACd,UAAI,KAAK,EAAE,QAAQ,CAAC;AAAA,IACxB;AAAA,EACJ,CAAC;AAED,MAAI,IAAI,SAAS,OAAO,KAAsB,QAA0B;AACpE,UAAM,SAAS,IAAI,MAAM;AACzB,QAAI;AACA,YAAM,cAAc,MAAM,uBAAW,eAAe,QAAQ,gBAAgB;AAC5E,UAAI,KAAK,WAAW;AAAA,IACxB,SAAS,GAAG;AACR,YAAM,UAAU,uBAAuB,QAAQ,WAAW,MAAM;AAChE,UAAI,OAAO,GAAG;AACd,UAAI,KAAK,EAAE,QAAQ,CAAC;AAAA,IACxB;AAAA,EACJ,CAAC;AAED,MAAI,IAAI,cAAc,OAAO,KAAsB,QAA0B;AACzE,UAAM,SAAS,IAAI,MAAM;AACzB,UAAM,SAAS,IAAI,MAAM;AACzB,UAAM,OAAO,KAAK,MAAM,IAAI,MAAM,IAAc;AAEhD,QAAI;AACA,YAAM,OAAO,MAAM,uBAAW,eAAe,QAAQ,QAAQ,IAAI;AACjE,UAAI,KAAK,sBAAQ,CAAC,CAAC;AAAA,IACvB,SAAS,GAAG;AACR,YAAM,UAAU,uBAAuB,QAAQ,WAAW,MAAM;AAChE,UAAI,OAAO,GAAG;AACd,UAAI,KAAK,EAAE,QAAQ,CAAC;AAAA,IACxB;AAAA,EACJ,CAAC;AAED,SAAO;AACX;",
|
|
6
|
-
"names": ["express"]
|
|
7
|
-
}
|
package/build/api.d.ts
DELETED
package/build/api.mjs
DELETED
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
// src-backend/api.ts
|
|
2
|
-
import { matchMaker } from "@colyseus/core";
|
|
3
|
-
import express from "express";
|
|
4
|
-
import { OSUtils } from "node-os-utils";
|
|
5
|
-
var osutils = new OSUtils();
|
|
6
|
-
var UNAVAILABLE_ROOM_ERROR = "@colyseus/monitor: room $roomId is not available anymore.";
|
|
7
|
-
function getAPI(opts) {
|
|
8
|
-
const api = express.Router();
|
|
9
|
-
api.get("/", async (req, res) => {
|
|
10
|
-
try {
|
|
11
|
-
const rooms = await matchMaker.query({});
|
|
12
|
-
const columns = opts.columns || ["roomId", "name", "clients", "maxClients", "locked", "elapsedTime"];
|
|
13
|
-
if (!opts.columns && rooms[0] && rooms[0].publicAddress !== void 0) {
|
|
14
|
-
columns.push("publicAddress");
|
|
15
|
-
}
|
|
16
|
-
let connections = 0;
|
|
17
|
-
const cpuUsage = await osutils.cpu.usage();
|
|
18
|
-
const cpu = cpuUsage.success ? cpuUsage.data : NaN;
|
|
19
|
-
const memoryInfo = await osutils.memory.info();
|
|
20
|
-
const totalMemMb = memoryInfo.success ? memoryInfo.data.total?.toMB() : NaN;
|
|
21
|
-
const usedMemMb = memoryInfo.success ? memoryInfo.data.used?.toMB() : NaN;
|
|
22
|
-
res.json({
|
|
23
|
-
columns,
|
|
24
|
-
rooms: rooms.map((room) => {
|
|
25
|
-
const data = JSON.parse(JSON.stringify(room));
|
|
26
|
-
connections += room.clients;
|
|
27
|
-
data.locked = room.locked || false;
|
|
28
|
-
data.private = room.private;
|
|
29
|
-
data.maxClients = `${room.maxClients}`;
|
|
30
|
-
data.elapsedTime = Date.now() - new Date(room.createdAt).getTime();
|
|
31
|
-
return data;
|
|
32
|
-
}),
|
|
33
|
-
connections,
|
|
34
|
-
cpu,
|
|
35
|
-
memory: {
|
|
36
|
-
totalMemMb,
|
|
37
|
-
usedMemMb
|
|
38
|
-
}
|
|
39
|
-
});
|
|
40
|
-
} catch (e) {
|
|
41
|
-
const message = e.message;
|
|
42
|
-
console.error(message);
|
|
43
|
-
res.status(500);
|
|
44
|
-
res.json({ message });
|
|
45
|
-
}
|
|
46
|
-
});
|
|
47
|
-
api.get("/room", async (req, res) => {
|
|
48
|
-
const roomId = req.query.roomId;
|
|
49
|
-
try {
|
|
50
|
-
const inspectData = await matchMaker.remoteRoomCall(roomId, "getInspectData");
|
|
51
|
-
res.json(inspectData);
|
|
52
|
-
} catch (e) {
|
|
53
|
-
const message = UNAVAILABLE_ROOM_ERROR.replace("$roomId", roomId);
|
|
54
|
-
res.status(500);
|
|
55
|
-
res.json({ message });
|
|
56
|
-
}
|
|
57
|
-
});
|
|
58
|
-
api.get("/room/call", async (req, res) => {
|
|
59
|
-
const roomId = req.query.roomId;
|
|
60
|
-
const method = req.query.method;
|
|
61
|
-
const args = JSON.parse(req.query.args);
|
|
62
|
-
try {
|
|
63
|
-
const data = await matchMaker.remoteRoomCall(roomId, method, args);
|
|
64
|
-
res.json(data ?? {});
|
|
65
|
-
} catch (e) {
|
|
66
|
-
const message = UNAVAILABLE_ROOM_ERROR.replace("$roomId", roomId);
|
|
67
|
-
res.status(500);
|
|
68
|
-
res.json({ message });
|
|
69
|
-
}
|
|
70
|
-
});
|
|
71
|
-
return api;
|
|
72
|
-
}
|
|
73
|
-
export {
|
|
74
|
-
getAPI
|
|
75
|
-
};
|
package/build/api.mjs.map
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../src-backend/api.ts"],
|
|
4
|
-
"sourcesContent": ["import { matchMaker } from '@colyseus/core';\n\nimport express from 'express';\nimport { OSUtils } from 'node-os-utils';\n\nimport type { MonitorOptions } from './index.js';\n\nconst osutils = new OSUtils();\n\nconst UNAVAILABLE_ROOM_ERROR = \"@colyseus/monitor: room $roomId is not available anymore.\";\n\nexport function getAPI (opts: Partial<MonitorOptions>): express.Router {\n const api = express.Router();\n\n api.get(\"/\", async (req: express.Request, res: express.Response) => {\n try {\n const rooms: any[] = await matchMaker.query({});\n const columns = opts.columns || ['roomId', 'name', 'clients', 'maxClients', 'locked', 'elapsedTime'];\n\n // extend columns to expose \"publicAddress\", if present\n if (!opts.columns && rooms[0] && rooms[0].publicAddress !== undefined) {\n columns.push(\"publicAddress\");\n }\n\n let connections: number = 0;\n\n const cpuUsage = await osutils.cpu.usage();\n const cpu = (cpuUsage.success) ? cpuUsage.data : NaN;\n\n const memoryInfo = await osutils.memory.info();\n const totalMemMb = (memoryInfo.success) ? memoryInfo.data.total?.toMB() : NaN;\n const usedMemMb = (memoryInfo.success) ? memoryInfo.data.used?.toMB() : NaN;\n\n res.json({\n columns,\n rooms: rooms.map(room => {\n const data = JSON.parse(JSON.stringify(room));\n\n connections += room.clients;\n\n // additional data\n data.locked = room.locked || false;\n data.private = room.private;\n\n data.maxClients = `${room.maxClients}`;\n\n data.elapsedTime = Date.now() - new Date(room.createdAt).getTime();\n return data;\n }),\n\n connections,\n cpu,\n memory: {\n totalMemMb,\n usedMemMb \n },\n });\n } catch (e: any) {\n const message = e.message;\n console.error(message);\n res.status(500);\n res.json({ message });\n }\n });\n\n api.get(\"/room\", async (req: express.Request, res: express.Response) => {\n const roomId = req.query.roomId as string;\n try {\n const inspectData = await matchMaker.remoteRoomCall(roomId, \"getInspectData\");\n res.json(inspectData);\n } catch (e) {\n const message = UNAVAILABLE_ROOM_ERROR.replace(\"$roomId\", roomId);\n res.status(500);\n res.json({ message });\n }\n });\n\n api.get(\"/room/call\", async (req: express.Request, res: express.Response) => {\n const roomId = req.query.roomId as string;\n const method = req.query.method as string;\n const args = JSON.parse(req.query.args as string);\n\n try {\n const data = await matchMaker.remoteRoomCall(roomId, method, args);\n res.json(data ?? {});\n } catch (e) {\n const message = UNAVAILABLE_ROOM_ERROR.replace(\"$roomId\", roomId);\n res.status(500);\n res.json({ message });\n }\n });\n\n return api;\n}\n"],
|
|
5
|
-
"mappings": ";AAAA,SAAS,kBAAkB;AAE3B,OAAO,aAAa;AACpB,SAAS,eAAe;AAIxB,IAAM,UAAU,IAAI,QAAQ;AAE5B,IAAM,yBAAyB;AAExB,SAAS,OAAQ,MAA+C;AACnE,QAAM,MAAM,QAAQ,OAAO;AAE3B,MAAI,IAAI,KAAK,OAAO,KAAsB,QAA0B;AAChE,QAAI;AACA,YAAM,QAAe,MAAM,WAAW,MAAM,CAAC,CAAC;AAC9C,YAAM,UAAU,KAAK,WAAW,CAAC,UAAU,QAAQ,WAAW,cAAc,UAAU,aAAa;AAGnG,UAAI,CAAC,KAAK,WAAW,MAAM,CAAC,KAAK,MAAM,CAAC,EAAE,kBAAkB,QAAW;AACnE,gBAAQ,KAAK,eAAe;AAAA,MAChC;AAEA,UAAI,cAAsB;AAE1B,YAAM,WAAW,MAAM,QAAQ,IAAI,MAAM;AACzC,YAAM,MAAO,SAAS,UAAW,SAAS,OAAO;AAEjD,YAAM,aAAa,MAAM,QAAQ,OAAO,KAAK;AAC7C,YAAM,aAAc,WAAW,UAAW,WAAW,KAAK,OAAO,KAAK,IAAI;AAC1E,YAAM,YAAa,WAAW,UAAW,WAAW,KAAK,MAAM,KAAK,IAAI;AAExE,UAAI,KAAK;AAAA,QACL;AAAA,QACA,OAAO,MAAM,IAAI,UAAQ;AACrB,gBAAM,OAAO,KAAK,MAAM,KAAK,UAAU,IAAI,CAAC;AAE5C,yBAAe,KAAK;AAGpB,eAAK,SAAS,KAAK,UAAU;AAC7B,eAAK,UAAU,KAAK;AAEpB,eAAK,aAAa,GAAG,KAAK,UAAU;AAEpC,eAAK,cAAc,KAAK,IAAI,IAAI,IAAI,KAAK,KAAK,SAAS,EAAE,QAAQ;AACjE,iBAAO;AAAA,QACX,CAAC;AAAA,QAED;AAAA,QACA;AAAA,QACA,QAAQ;AAAA,UACJ;AAAA,UACA;AAAA,QACJ;AAAA,MACJ,CAAC;AAAA,IACL,SAAS,GAAQ;AACb,YAAM,UAAU,EAAE;AAClB,cAAQ,MAAM,OAAO;AACrB,UAAI,OAAO,GAAG;AACd,UAAI,KAAK,EAAE,QAAQ,CAAC;AAAA,IACxB;AAAA,EACJ,CAAC;AAED,MAAI,IAAI,SAAS,OAAO,KAAsB,QAA0B;AACpE,UAAM,SAAS,IAAI,MAAM;AACzB,QAAI;AACA,YAAM,cAAc,MAAM,WAAW,eAAe,QAAQ,gBAAgB;AAC5E,UAAI,KAAK,WAAW;AAAA,IACxB,SAAS,GAAG;AACR,YAAM,UAAU,uBAAuB,QAAQ,WAAW,MAAM;AAChE,UAAI,OAAO,GAAG;AACd,UAAI,KAAK,EAAE,QAAQ,CAAC;AAAA,IACxB;AAAA,EACJ,CAAC;AAED,MAAI,IAAI,cAAc,OAAO,KAAsB,QAA0B;AACzE,UAAM,SAAS,IAAI,MAAM;AACzB,UAAM,SAAS,IAAI,MAAM;AACzB,UAAM,OAAO,KAAK,MAAM,IAAI,MAAM,IAAc;AAEhD,QAAI;AACA,YAAM,OAAO,MAAM,WAAW,eAAe,QAAQ,QAAQ,IAAI;AACjE,UAAI,KAAK,QAAQ,CAAC,CAAC;AAAA,IACvB,SAAS,GAAG;AACR,YAAM,UAAU,uBAAuB,QAAQ,WAAW,MAAM;AAChE,UAAI,OAAO,GAAG;AACd,UAAI,KAAK,EAAE,QAAQ,CAAC;AAAA,IACxB;AAAA,EACJ,CAAC;AAED,SAAO;AACX;",
|
|
6
|
-
"names": []
|
|
7
|
-
}
|
package/src-backend/api.ts
DELETED
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
import { matchMaker } from '@colyseus/core';
|
|
2
|
-
|
|
3
|
-
import express from 'express';
|
|
4
|
-
import { OSUtils } from 'node-os-utils';
|
|
5
|
-
|
|
6
|
-
import type { MonitorOptions } from './index.js';
|
|
7
|
-
|
|
8
|
-
const osutils = new OSUtils();
|
|
9
|
-
|
|
10
|
-
const UNAVAILABLE_ROOM_ERROR = "@colyseus/monitor: room $roomId is not available anymore.";
|
|
11
|
-
|
|
12
|
-
export function getAPI (opts: Partial<MonitorOptions>): express.Router {
|
|
13
|
-
const api = express.Router();
|
|
14
|
-
|
|
15
|
-
api.get("/", async (req: express.Request, res: express.Response) => {
|
|
16
|
-
try {
|
|
17
|
-
const rooms: any[] = await matchMaker.query({});
|
|
18
|
-
const columns = opts.columns || ['roomId', 'name', 'clients', 'maxClients', 'locked', 'elapsedTime'];
|
|
19
|
-
|
|
20
|
-
// extend columns to expose "publicAddress", if present
|
|
21
|
-
if (!opts.columns && rooms[0] && rooms[0].publicAddress !== undefined) {
|
|
22
|
-
columns.push("publicAddress");
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
let connections: number = 0;
|
|
26
|
-
|
|
27
|
-
const cpuUsage = await osutils.cpu.usage();
|
|
28
|
-
const cpu = (cpuUsage.success) ? cpuUsage.data : NaN;
|
|
29
|
-
|
|
30
|
-
const memoryInfo = await osutils.memory.info();
|
|
31
|
-
const totalMemMb = (memoryInfo.success) ? memoryInfo.data.total?.toMB() : NaN;
|
|
32
|
-
const usedMemMb = (memoryInfo.success) ? memoryInfo.data.used?.toMB() : NaN;
|
|
33
|
-
|
|
34
|
-
res.json({
|
|
35
|
-
columns,
|
|
36
|
-
rooms: rooms.map(room => {
|
|
37
|
-
const data = JSON.parse(JSON.stringify(room));
|
|
38
|
-
|
|
39
|
-
connections += room.clients;
|
|
40
|
-
|
|
41
|
-
// additional data
|
|
42
|
-
data.locked = room.locked || false;
|
|
43
|
-
data.private = room.private;
|
|
44
|
-
|
|
45
|
-
data.maxClients = `${room.maxClients}`;
|
|
46
|
-
|
|
47
|
-
data.elapsedTime = Date.now() - new Date(room.createdAt).getTime();
|
|
48
|
-
return data;
|
|
49
|
-
}),
|
|
50
|
-
|
|
51
|
-
connections,
|
|
52
|
-
cpu,
|
|
53
|
-
memory: {
|
|
54
|
-
totalMemMb,
|
|
55
|
-
usedMemMb
|
|
56
|
-
},
|
|
57
|
-
});
|
|
58
|
-
} catch (e: any) {
|
|
59
|
-
const message = e.message;
|
|
60
|
-
console.error(message);
|
|
61
|
-
res.status(500);
|
|
62
|
-
res.json({ message });
|
|
63
|
-
}
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
api.get("/room", async (req: express.Request, res: express.Response) => {
|
|
67
|
-
const roomId = req.query.roomId as string;
|
|
68
|
-
try {
|
|
69
|
-
const inspectData = await matchMaker.remoteRoomCall(roomId, "getInspectData");
|
|
70
|
-
res.json(inspectData);
|
|
71
|
-
} catch (e) {
|
|
72
|
-
const message = UNAVAILABLE_ROOM_ERROR.replace("$roomId", roomId);
|
|
73
|
-
res.status(500);
|
|
74
|
-
res.json({ message });
|
|
75
|
-
}
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
api.get("/room/call", async (req: express.Request, res: express.Response) => {
|
|
79
|
-
const roomId = req.query.roomId as string;
|
|
80
|
-
const method = req.query.method as string;
|
|
81
|
-
const args = JSON.parse(req.query.args as string);
|
|
82
|
-
|
|
83
|
-
try {
|
|
84
|
-
const data = await matchMaker.remoteRoomCall(roomId, method, args);
|
|
85
|
-
res.json(data ?? {});
|
|
86
|
-
} catch (e) {
|
|
87
|
-
const message = UNAVAILABLE_ROOM_ERROR.replace("$roomId", roomId);
|
|
88
|
-
res.status(500);
|
|
89
|
-
res.json({ message });
|
|
90
|
-
}
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
return api;
|
|
94
|
-
}
|