@colyseus/tools 0.15.20 → 0.15.22

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/LICENSE CHANGED
@@ -1,4 +1,5 @@
1
- Copyright (c) 2021 Lucid Sight
1
+ Copyright (c) 2023 Endel Dreyer
2
+ Copyright (c) 2021-2022 Lucid Sight
2
3
  Copyright (c) 2015-2021 Endel Dreyer
3
4
 
4
5
  MIT License:
package/README.md CHANGED
@@ -1,16 +1,16 @@
1
1
  <div align="center">
2
2
  <a href="https://github.com/colyseus/colyseus">
3
- <img src="media/header.png?raw=true" />
3
+ <img src="media/logo.svg?raw=true" width="60%" height="300" />
4
4
  </a>
5
5
  <br>
6
6
  <br>
7
7
  <a href="https://npmjs.com/package/colyseus">
8
8
  <img src="https://img.shields.io/npm/dm/colyseus.svg?style=for-the-badge&logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAQAAAC1+jfqAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QAAKqNIzIAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAAHdElNRQfjAgETESWYxR33AAAAtElEQVQoz4WQMQrCQBRE38Z0QoTcwF4Qg1h4BO0sxGOk80iCtViksrIQRRBTewWxMI1mbELYjYu+4rPMDPtn12ChMT3gavb4US5Jym0tcBIta3oDHv4Gwmr7nC4QAxBrCdzM2q6XqUnm9m9r59h7Rc0n2pFv24k4ttGMUXW+sGELTJjSr7QDKuqLS6UKFChVWWuFkZw9Z2AAvAirKT+JTlppIRnd6XgaP4goefI2Shj++OnjB3tBmHYK8z9zAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDE5LTAyLTAxVDE4OjE3OjM3KzAxOjAwGQQixQAAACV0RVh0ZGF0ZTptb2RpZnkAMjAxOS0wMi0wMVQxODoxNzozNyswMTowMGhZmnkAAAAZdEVYdFNvZnR3YXJlAHd3dy5pbmtzY2FwZS5vcmeb7jwaAAAAAElFTkSuQmCC">
9
9
  </a>
10
- <a href="http://discuss.colyseus.io" title="Discuss on Forum">
10
+ <a href="https://github.com/colyseus/colyseus/discussions" title="Discuss on Forum">
11
11
  <img src="https://img.shields.io/badge/discuss-on%20forum-brightgreen.svg?style=for-the-badge&colorB=0069b8&logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAQAAAC1+jfqAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QAAKqNIzIAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAAHdElNRQfjAgETDROxCNUzAAABB0lEQVQoz4WRvyvEARjGP193CnWRH+dHQmGwKZtFGcSmxHAL400GN95ktIpV2dzlLzDJgsGgGNRdDAzoQueS/PgY3HXHyT3T+/Y87/s89UANBKXBdoZo5J6L4K1K5ZxHfnjnlQUf3bKvkgy57a0r9hS3cXfMO1kWJMza++tj3Ac7/LY343x1NA9cNmYMwnSS/SP8JVFuSJmr44iFqvtmpjhmhBCrOOazCesq6H4P3bPBjFoIBydOk2bUA17I080Es+wSZ51B4DIA2zgjSpYcEe44Js01G0XjRcCU+y4ZMrDeLmfc9EnVd5M/o0VMeu6nJZxWJivLmhyw1WHTvrr2b4+2OFqra+ALwouTMDcqmjMAAAAldEVYdGRhdGU6Y3JlYXRlADIwMTktMDItMDFUMTg6MTM6MTkrMDE6MDAC9f6fAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDE5LTAyLTAxVDE4OjEzOjE5KzAxOjAwc6hGIwAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAAASUVORK5CYII=" alt="Discussion forum" />
12
12
  </a>
13
- <a href="https://discord.gg/RY8rRS7">
13
+ <a href="http://chat.colyseus.io">
14
14
  <img src="https://img.shields.io/discord/525739117951320081.svg?style=for-the-badge&colorB=7581dc&logo=discord&logoColor=white">
15
15
  </a>
16
16
  <h3>
@@ -19,7 +19,7 @@
19
19
  </div>
20
20
 
21
21
  Colyseus is an Authoritative Multiplayer Framework for Node.js, with clients
22
- available for the Web, Unity3d, Defold, Haxe, and Cocos2d-X. ([See official clients](#%EF%B8%8F-official-client-integration))
22
+ available for the Web, Unity3d, Defold, Haxe, and Cocos. ([See official clients](#%EF%B8%8F-official-client-integration))
23
23
 
24
24
  The project focuses on providing synchronizable data structures for realtime and
25
25
  turn-based games, matchmaking, and ease of usage both on the server-side and
@@ -28,81 +28,35 @@ client-side.
28
28
  The mission of the framework is to be a standard netcode & matchmaking solution
29
29
  for any kind of project you can think of!
30
30
 
31
- You're encouraged to take a look on [some games being developed with
32
- it](https://discuss.colyseus.io/category/5/showcase) and make your own!
33
-
34
- > ⭐️ Enjoying Colyseus? Show your support by starring the project on GitHub ⭐️
35
-
36
- ## What Colyseus provides to you:
31
+ ## Key features:
37
32
 
38
33
  - WebSocket-based communication
39
34
  - Simple API in the server-side and client-side.
40
- - Automatic state synchronization between server and client.
41
- - Matchmaking clients into game sessions
35
+ - Automatic state synchronization from server-to-client (delta compressed)
36
+ - Matchmaking clients into game rooms/sessions
42
37
  - Scale vertically or horizontally
43
38
 
44
- ## What Colyseus won't provide:
45
-
46
- - Game Engine: Colyseus is agnostic of the engine you're using. Need Physics? Add your own logic / package.
47
- - Database: It's up to you to configure and select which database you'd like to use.
48
-
49
- See [roadmap](https://github.com/colyseus/colyseus/wiki/Roadmap) for our future plans.
39
+ See [public roadmap](https://github.com/colyseus/colyseus/wiki/Public-Roadmap) for future plans.
50
40
 
51
41
  # 🚀 Quickstart
52
42
 
53
- Create a bare-bones Colyseus server by using `npm init colyseus-app`.
43
+ Create a bare-bones Colyseus server by using `npm create colyseus-app@latest`:
54
44
 
55
45
  ```
56
- npm init colyseus-app my-colyseus-server
46
+ npm create colyseus-app@latest my-colyseus-server
57
47
  cd my-colyseus-server
58
48
  npm start
59
49
  ```
60
- # 🏟 Colyseus Arena: Fast & Scalable Cloud Hosting
61
-
62
- - Looking for a fully managed solution for your Colyseus game server?
63
- - Want to focus on game development and not on the hosting and infrastructure?
64
- - Launching a production title and need a solution for 1,000 to 100,000+ CCUs?
65
-
66
- If so [Colyseus Arena](https://www.colyseus.io/arena) cloud hosting is the solution you are looking for. Easily upload your existing Colyseus Server code and get started today for Free!
67
-
68
- # 🕹️ Official Client Integration
69
50
 
70
- - [JavaScript/TypeScript](https://github.com/colyseus/colyseus.js)
71
- - [Unity](https://github.com/colyseus/colyseus-unity3d) ([unity3d.com](https://unity3d.com/))
72
- - [Defold Engine](https://github.com/colyseus/colyseus-defold) ([defold.com](https://www.defold.com/))
73
- - [Haxe](https://github.com/colyseus/colyseus-hx) ([haxe.org](https://haxe.org/))
74
- - [Construct 3](https://github.com/colyseus/colyseus-construct3) ([construct3.net](https://www.construct.net/))
75
- - [Cocos2d-x](https://github.com/colyseus/colyseus-cocos2d-x) ([cocos2d-x.org](https://cocos2d-x.org/))
51
+ # Sponsors
76
52
 
77
- # 🛠️ Tools
53
+ The sustainability of the project relies on **Colyseus Cloud** subscriptions and sponsorships. If you are not using Colyseus Cloud, please consider [sponsoring the project](https://github.com/sponsors/endel) 💖
78
54
 
79
- - [@colyseus/proxy](https://github.com/colyseus/proxy) - Proxy & Service Discovery for scaling Colyseus
80
- - [@colyseus/monitor](https://github.com/colyseus/colyseus-monitor) - A Web Monitoring Panel for Colyseus
81
- - [@colyseus/loadtest](https://github.com/colyseus/colyseus-loadtest) - Utility tool for load testing Colyseus
55
+ <a href="https://colyseus.io/sponsorkit/sponsors.svg">
56
+ <img src="https://github.com/colyseus/colyseus.github.io/blob/master/sponsorkit/sponsors.svg?raw=1" width="100%" />
57
+ </a>
82
58
 
83
- ## Tools made by the community ❤️
84
-
85
- - [godot-colyseus](https://github.com/gsioteam/godot-colyseus): Colyseus SDK for Godot, written in GDScript (by [@gsioteam](https://github.com/gsioteam))
86
- - [colyseus-ue4](https://github.com/charisma-ai/colyseus-ue4): Colyseus SDK for Unreal Engine 4 (by [@bensalilijames](https://github.com/bensalilijames))
87
- - [colyseus-hxjs](https://github.com/serjek/colyseus-hxjs): Haxe externs for colyseus server (by [@serjek](https://github.com/serjek))
88
- - [colyseus-kotlin](https://github.com/doorbash/colyseus-kotlin): Client for Java/Kotlin (by [@doorbash](https://github.com/doorbash))
89
- - [Stencyl Extension](http://community.stencyl.com/index.php/topic,61150.0.html): [Stencyl](http://stencyl.com) extension to communicate with a Colyseus server (by [MdotEdot](http://www.stencyl.com/users/index/32424))
90
- - [Colyseus-ObjC](https://github.com/swittk/Colyseus-ObjC): Client for Objective C (by [@swittk](https://github.com/swittk))
91
- - [Colyseus-for-C2](https://github.com/Keevle/Colyseus-for-C2): Client for Construct 2 (by [@Keevle](https://github.com/Keevle))
92
-
93
- # Usage examples
94
-
95
- See the [official examples](https://github.com/colyseus/colyseus-examples) for
96
- usage reference with the latest version of Colyseus.
97
-
98
- - [Tech Demo: Shooting Gallery](https://github.com/colyseus/unity-demo-shooting-gallery) - Unity + Colyseus "Shooting Gallery" Tech Demo
99
- - [Colyseus + PixiJS Boilerplate](https://colyseus-pixijs-boilerplate.herokuapp.com/) ([source-code](https://github.com/endel/colyseus-pixijs-boilerplate)) - Simplistic agar.io implementation using [PixiJS](https://github.com/pixijs/pixi.js)
100
- - [Colyseus + BabylonJS Boilerplate](https://babylonjs-multiplayer.herokuapp.com/) ([source-code](https://github.com/endel/babylonjs-multiplayer-boilerplate)) - Bare-bones [BabylonJS](https://github.com/BabylonJS/Babylon.js) example
101
- - [Tic Tac Toe](https://tictactoe-colyseus.herokuapp.com) ([source-code](https://github.com/endel/tic-tac-toe)) - Tic Tac Toe using [PixiJS](https://github.com/pixijs/pixi.js) and [Defold Engine](https://defold.com)
102
- - [Collaborative Drawing Prototype](https://colyseus-drawing-prototype.herokuapp.com/) ([source-code](https://github.com/endel/colyseus-collaborative-drawing)) - Collaborative drawing using HTML5 canvas.
103
- - (outdated: < v0.8.x): [tanx](https://playcanvas.com/project/367035/overview/tanxcolyseus), [react-example](https://github.com/endel/colyseus-react-example), [LD35 entry: dotower](http://ludumdare.com/compo/ludum-dare-35/?action=preview&uid=50958)
104
-
105
- # Contributors
59
+ # Contributors
106
60
 
107
61
  Thanks goes to these wonderful people ([emoji key](https://github.com/kentcdodds/all-contributors#emoji-key)):
108
62
 
@@ -121,7 +75,7 @@ Thanks goes to these wonderful people ([emoji key](https://github.com/kentcdodds
121
75
  </tr>
122
76
  <tr>
123
77
  <td align="center"><a href="https://github.com/enriqueto"><img src="https://avatars2.githubusercontent.com/u/5557196?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Enriqueto</b></sub></a><br /><a href="#business-enriqueto" title="Business development">💼</a></td>
124
- <td align="center"><a href="https://github.com/fazriz"><img src="https://avatars0.githubusercontent.com/u/2628698?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Fazri Zubair</b></sub></a><br /><a href="#question-fazriz" title="Answering Questions">💬</a> <a href="https://github.com/colyseus/colyseus/commits?author=fazriz" title="Code">💻</a> <a href="#ideas-fazriz" title="Ideas, Planning, & Feedback">🤔</a> <a href="#business-fazriz" title="Business development">💼</a></td>
78
+ <td align="center"><a href="https://github.com/fazriz"><img src="https://avatars0.githubusercontent.com/u/2628698?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Fazri Zubair</b></sub></a><br /><a href="#business-fazriz" title="Business development">💼</a></td>
125
79
  <td align="center"><a href="https://twitter.com/Federkun"><img src="https://avatars2.githubusercontent.com/u/21344385?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Federico</b></sub></a><br /><a href="https://github.com/colyseus/colyseus/issues?q=author%3AFederkun" title="Bug reports">🐛</a> <a href="https://github.com/colyseus/colyseus/commits?author=Federkun" title="Code">💻</a></td>
126
80
  <td align="center"><a href="https://github.com/mobyjames/"><img src="https://avatars0.githubusercontent.com/u/1327007?v=4?s=100" width="100px;" alt=""/><br /><sub><b>James Jacoby</b></sub></a><br /><a href="#question-mobyjames" title="Answering Questions">💬</a> <a href="#example-mobyjames" title="Examples">💡</a> <a href="#content-mobyjames" title="Content">🖋</a></td>
127
81
  <td align="center"><a href="http://wenish.github.io/portfolio/"><img src="https://avatars0.githubusercontent.com/u/18367963?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Jonas Voland</b></sub></a><br /><a href="#question-Wenish" title="Answering Questions">💬</a> <a href="https://github.com/colyseus/colyseus/issues?q=author%3AWenish" title="Bug reports">🐛</a> <a href="https://github.com/colyseus/colyseus/commits?author=Wenish" title="Code">💻</a> <a href="#ideas-Wenish" title="Ideas, Planning, & Feedback">🤔</a> <a href="#example-Wenish" title="Examples">💡</a></td>
@@ -155,10 +109,6 @@ guide](.github/CONTRIBUTING.md) for guidelines about how to proceed. Join us!
155
109
  Everyone interacting in Colyseus and its sub-projects' codebases, issue trackers
156
110
  and chat rooms is expected to follow the [code of conduct](CODE_OF_CONDUCT.md).
157
111
 
158
- # Backers / Supporters via Patreon
159
-
160
- As of February 2021, Colyseus is owned and sponsored by [Lucid Sight](https://www.lucidsight.com/). A warm **thank you** for previous supporters of the project is forever documented in the [early supporters wiki page](https://github.com/colyseus/colyseus/wiki/Early-supporters-(2017-2021)).
161
-
162
112
  # License
163
113
 
164
114
  MIT
package/build/index.js CHANGED
@@ -196,6 +196,9 @@ async function getTransport(options) {
196
196
  if (options.initializeExpress) {
197
197
  await options.initializeExpress(app);
198
198
  }
199
+ app.get("/__healthcheck", (req, res) => {
200
+ res.status(200).end();
201
+ });
199
202
  app.get("/__cloudstats", async (req, res) => {
200
203
  if (process.env.CLOUD_SECRET && req.headers.authorization !== process.env.CLOUD_SECRET) {
201
204
  res.status(401).end();
@@ -206,7 +209,7 @@ async function getTransport(options) {
206
209
  for (const processId in roomCountPerProcess) {
207
210
  rooms += Number(roomCountPerProcess[processId]);
208
211
  }
209
- const ccu = await import_core.matchMaker.presence.get("_ccu");
212
+ const ccu = await import_core.matchMaker.stats.getGlobalCCU();
210
213
  const mem = await import_node_os_utils.default.mem.used();
211
214
  const cpu = await import_node_os_utils.default.cpu.usage() / 100;
212
215
  res.json({
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/index.ts"],
4
- "sourcesContent": ["import fs from \"fs\";\nimport os from \"os\";\nimport http from \"http\";\nimport path from \"path\";\nimport cors from \"cors\";\nimport express from \"express\";\nimport dotenv from \"dotenv\";\nimport osUtils from \"node-os-utils\";\nimport { logger, Server, ServerOptions, Transport, matchMaker } from '@colyseus/core';\nimport { WebSocketTransport } from '@colyseus/ws-transport';\n\n// try to import uWebSockets-express compatibility layer.\nlet uWebSocketsExpressCompatibility: any = undefined;\ntry { uWebSocketsExpressCompatibility = require('uwebsockets-express').default; } catch (e) {}\n\nlet BunWebSockets: any = undefined;\ntry { BunWebSockets = require('@colyseus/bun-websockets'); } catch (e) {}\n\nfunction getNodeEnv() {\n return process.env.NODE_ENV || \"development\";\n}\n\nfunction getRegion() {\n // EU, NA, AS, AF, AU, SA, UNKNOWN\n return (process.env.REGION || \"unknown\").toLowerCase();\n}\n\nfunction loadEnvFile(envFileOptions: string[], log: 'none' | 'success' | 'both' = 'none') {\n const envPaths = [];\n envFileOptions.forEach((envFilename) => {\n envPaths.push(path.resolve(path.dirname(require?.main?.filename || process.cwd()), \"..\", envFilename));\n envPaths.push(path.resolve(process.cwd(), envFilename));\n });\n\n // return the first .env path found\n const envPath = envPaths.find((envPath) => fs.existsSync(envPath));\n\n if (envPath) {\n dotenv.config({ path: envPath });\n\n if (log !== \"none\") {\n logger.info(`\u2705 ${path.basename(envPath)} loaded.`);\n }\n\n } else if (log === \"both\") {\n logger.info(`\u2139\uFE0F optional .env file not found: ${envFileOptions.join(\", \")}`);\n }\n}\n\n// load .env.cloud defined on admin panel\nif (process.env.COLYSEUS_CLOUD !== undefined) {\n loadEnvFile([`.env.cloud`]);\n}\n\n// (overrides previous env configs)\nloadEnvFile([`.env.${getNodeEnv()}`, `.env`], 'both');\n\nif (process.env.REGION !== undefined) {\n loadEnvFile([`.env.${getRegion()}.${getNodeEnv()}`], 'success');\n}\n\nexport interface ConfigOptions {\n options?: ServerOptions,\n displayLogs?: boolean,\n getId?: () => string,\n initializeTransport?: (options: any) => Transport,\n initializeExpress?: (app: express.Express) => void,\n initializeGameServer?: (app: Server) => void,\n beforeListen?: () => void,\n}\n\nconst ALLOWED_KEYS: { [key in keyof ConfigOptions]: string } = {\n 'displayLogs': \"boolean\",\n 'options': \"object\",\n 'getId': \"function\",\n 'initializeTransport': \"function\",\n 'initializeExpress': \"function\",\n 'initializeGameServer': \"function\",\n 'beforeListen': \"function\"\n};\n\nexport default function (options: ConfigOptions) {\n for (const option in options) {\n if (!ALLOWED_KEYS[option]) {\n throw new Error(`\u274C Invalid option '${option}'. Allowed options are: ${Object.keys(ALLOWED_KEYS).join(\", \")}`);\n }\n if(options[option] !== undefined && typeof(options[option]) !== ALLOWED_KEYS[option]) {\n throw new Error(`\u274C Invalid type for ${option}: please provide a ${ALLOWED_KEYS[option]} value.`);\n }\n }\n\n return options;\n}\n\n/**\n * Listen on your development environment\n * @param options Application options\n * @param port Port number to bind Colyseus + Express\n */\nexport async function listen(\n options: ConfigOptions,\n port: number = Number(process.env.PORT || 2567),\n) {\n const serverOptions = options.options || {};\n options.displayLogs = options.displayLogs ?? true;\n\n // Force 2567 port on Colyseus Cloud\n if (process.env.COLYSEUS_CLOUD !== undefined) {\n port = 2567;\n }\n\n //\n // Handling multiple processes\n // Use NODE_APP_INSTANCE to play nicely with pm2\n //\n const processNumber = Number(process.env.NODE_APP_INSTANCE || \"0\");\n port += processNumber;\n\n // automatically configure for production under Colyseus Cloud\n if (process.env.COLYSEUS_CLOUD !== undefined) {\n // special configuration is required when using multiple processes\n const useRedisConfig = (os.cpus().length > 1) || (process.env.REDIS_URI !== undefined);\n\n if (!serverOptions.driver && useRedisConfig) {\n let RedisDriver: any = undefined;\n try {\n RedisDriver = require('@colyseus/redis-driver').RedisDriver;\n serverOptions.driver = new RedisDriver(process.env.REDIS_URI);\n } catch (e) {\n logger.warn(\"\");\n logger.warn(\"\u274C coult not initialize RedisDriver.\");\n logger.warn(\"\uD83D\uDC49 npm install --save @colyseus/redis-driver\");\n logger.warn(\"\");\n }\n }\n\n if (!serverOptions.presence && useRedisConfig) {\n let RedisPresence: any = undefined;\n try {\n RedisPresence = require('@colyseus/redis-presence').RedisPresence;\n serverOptions.presence = new RedisPresence(process.env.REDIS_URI);\n } catch (e) {\n logger.warn(\"\");\n logger.warn(\"\u274C coult not initialize RedisPresence.\");\n logger.warn(\"\uD83D\uDC49 npm install --save @colyseus/redis-presence\");\n logger.warn(\"\");\n }\n }\n\n // force \"publicAddress\" when deployed on \"Colyseus Cloud\".\n serverOptions.publicAddress = process.env.SUBDOMAIN + \".\" + process.env.SERVER_NAME;\n\n // nginx is responsible for forwarding /{port}/ to this process\n if (useRedisConfig) {\n serverOptions.publicAddress += \"/\" + port;\n }\n }\n\n const transport = await getTransport(options);\n const gameServer = new Server({\n ...serverOptions,\n transport,\n });\n await options.initializeGameServer?.(gameServer);\n await options.beforeListen?.();\n\n\n if (process.env.COLYSEUS_CLOUD !== undefined) {\n // listening on socket\n // @ts-ignore\n await gameServer.listen(`/run/colyseus/${port}.sock`);\n\n } else {\n // listening on port\n await gameServer.listen(port);\n }\n\n // notify process manager (production)\n if (typeof(process.send) === \"function\") {\n process.send('ready');\n }\n\n if (options.displayLogs) {\n logger.info(`\u2694\uFE0F Listening on http://localhost:${port}`);\n }\n return gameServer;\n}\n\n\nexport async function getTransport(options: ConfigOptions) {\n let transport: Transport;\n\n if (!options.initializeTransport) {\n if (BunWebSockets !== undefined) {\n // @colyseus/bun-websockets\n options.initializeTransport = (options: any) => new BunWebSockets.BunWebSockets(options);\n\n } else {\n // use WebSocketTransport by default\n options.initializeTransport = (options: any) => new WebSocketTransport(options);\n }\n }\n\n let app: express.Express | undefined = express();\n let server = http.createServer(app);\n\n transport = await options.initializeTransport({ server });\n\n //\n // TODO: refactor me!\n // BunWebSockets: There's no need to instantiate \"app\" and \"server\" above\n //\n if (transport['expressApp']) {\n app = transport['expressApp'];\n }\n\n if (options.initializeExpress) {\n // uWebSockets.js + Express compatibility layer.\n // @ts-ignore\n if (transport['app']) {\n if (typeof (uWebSocketsExpressCompatibility) === \"function\") {\n if (options.displayLogs){\n logger.info(\"\u2705 uWebSockets.js + Express compatibility enabled\");\n }\n\n // @ts-ignore\n server = undefined;\n // @ts-ignore\n app = uWebSocketsExpressCompatibility(transport['app']);\n\n } else {\n if (options.displayLogs) {\n logger.warn(\"\");\n logger.warn(\"\u274C uWebSockets.js + Express compatibility mode couldn't be loaded, run the following command to fix:\");\n logger.warn(\"\uD83D\uDC49 npm install --save uwebsockets-express\");\n logger.warn(\"\");\n }\n app = undefined;\n }\n }\n }\n\n if (app) {\n // Enable CORS + JSON parsing.\n app.use(cors());\n app.use(express.json());\n\n if (options.initializeExpress) {\n await options.initializeExpress(app);\n }\n\n app.get(\"/__cloudstats\", async (req, res) => {\n if (\n process.env.CLOUD_SECRET &&\n req.headers.authorization !== process.env.CLOUD_SECRET\n ) {\n res.status(401).end();\n return;\n }\n\n const roomCountPerProcess = await matchMaker.presence.hgetall(\"roomcount\");\n let rooms = 0;\n for (const processId in roomCountPerProcess) {\n rooms += Number(roomCountPerProcess[processId]);\n }\n\n const ccu = await matchMaker.presence.get(\"_ccu\");\n const mem = await osUtils.mem.used();\n const cpu = (await osUtils.cpu.usage()) / 100;\n\n res.json({\n version: 1,\n mem: (mem.usedMemMb / mem.totalMemMb),\n cpu,\n ccu,\n rooms,\n });\n });\n\n if (options.displayLogs) {\n logger.info(\"\u2705 Express initialized\");\n }\n }\n\n return transport;\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import fs from \"fs\";\nimport os from \"os\";\nimport http from \"http\";\nimport path from \"path\";\nimport cors from \"cors\";\nimport express from \"express\";\nimport dotenv from \"dotenv\";\nimport osUtils from \"node-os-utils\";\nimport { logger, Server, ServerOptions, Transport, matchMaker } from '@colyseus/core';\nimport { WebSocketTransport } from '@colyseus/ws-transport';\n\n// try to import uWebSockets-express compatibility layer.\nlet uWebSocketsExpressCompatibility: any = undefined;\ntry { uWebSocketsExpressCompatibility = require('uwebsockets-express').default; } catch (e) {}\n\nlet BunWebSockets: any = undefined;\ntry { BunWebSockets = require('@colyseus/bun-websockets'); } catch (e) {}\n\nfunction getNodeEnv() {\n return process.env.NODE_ENV || \"development\";\n}\n\nfunction getRegion() {\n // EU, NA, AS, AF, AU, SA, UNKNOWN\n return (process.env.REGION || \"unknown\").toLowerCase();\n}\n\nfunction loadEnvFile(envFileOptions: string[], log: 'none' | 'success' | 'both' = 'none') {\n const envPaths = [];\n envFileOptions.forEach((envFilename) => {\n envPaths.push(path.resolve(path.dirname(require?.main?.filename || process.cwd()), \"..\", envFilename));\n envPaths.push(path.resolve(process.cwd(), envFilename));\n });\n\n // return the first .env path found\n const envPath = envPaths.find((envPath) => fs.existsSync(envPath));\n\n if (envPath) {\n dotenv.config({ path: envPath });\n\n if (log !== \"none\") {\n logger.info(`\u2705 ${path.basename(envPath)} loaded.`);\n }\n\n } else if (log === \"both\") {\n logger.info(`\u2139\uFE0F optional .env file not found: ${envFileOptions.join(\", \")}`);\n }\n}\n\n// load .env.cloud defined on admin panel\nif (process.env.COLYSEUS_CLOUD !== undefined) {\n loadEnvFile([`.env.cloud`]);\n}\n\n// (overrides previous env configs)\nloadEnvFile([`.env.${getNodeEnv()}`, `.env`], 'both');\n\nif (process.env.REGION !== undefined) {\n loadEnvFile([`.env.${getRegion()}.${getNodeEnv()}`], 'success');\n}\n\nexport interface ConfigOptions {\n options?: ServerOptions,\n displayLogs?: boolean,\n getId?: () => string,\n initializeTransport?: (options: any) => Transport,\n initializeExpress?: (app: express.Express) => void,\n initializeGameServer?: (app: Server) => void,\n beforeListen?: () => void,\n}\n\nconst ALLOWED_KEYS: { [key in keyof ConfigOptions]: string } = {\n 'displayLogs': \"boolean\",\n 'options': \"object\",\n 'getId': \"function\",\n 'initializeTransport': \"function\",\n 'initializeExpress': \"function\",\n 'initializeGameServer': \"function\",\n 'beforeListen': \"function\"\n};\n\nexport default function (options: ConfigOptions) {\n for (const option in options) {\n if (!ALLOWED_KEYS[option]) {\n throw new Error(`\u274C Invalid option '${option}'. Allowed options are: ${Object.keys(ALLOWED_KEYS).join(\", \")}`);\n }\n if(options[option] !== undefined && typeof(options[option]) !== ALLOWED_KEYS[option]) {\n throw new Error(`\u274C Invalid type for ${option}: please provide a ${ALLOWED_KEYS[option]} value.`);\n }\n }\n\n return options;\n}\n\n/**\n * Listen on your development environment\n * @param options Application options\n * @param port Port number to bind Colyseus + Express\n */\nexport async function listen(\n options: ConfigOptions,\n port: number = Number(process.env.PORT || 2567),\n) {\n const serverOptions = options.options || {};\n options.displayLogs = options.displayLogs ?? true;\n\n // Force 2567 port on Colyseus Cloud\n if (process.env.COLYSEUS_CLOUD !== undefined) {\n port = 2567;\n }\n\n //\n // Handling multiple processes\n // Use NODE_APP_INSTANCE to play nicely with pm2\n //\n const processNumber = Number(process.env.NODE_APP_INSTANCE || \"0\");\n port += processNumber;\n\n // automatically configure for production under Colyseus Cloud\n if (process.env.COLYSEUS_CLOUD !== undefined) {\n // special configuration is required when using multiple processes\n const useRedisConfig = (os.cpus().length > 1) || (process.env.REDIS_URI !== undefined);\n\n if (!serverOptions.driver && useRedisConfig) {\n let RedisDriver: any = undefined;\n try {\n RedisDriver = require('@colyseus/redis-driver').RedisDriver;\n serverOptions.driver = new RedisDriver(process.env.REDIS_URI);\n } catch (e) {\n logger.warn(\"\");\n logger.warn(\"\u274C coult not initialize RedisDriver.\");\n logger.warn(\"\uD83D\uDC49 npm install --save @colyseus/redis-driver\");\n logger.warn(\"\");\n }\n }\n\n if (!serverOptions.presence && useRedisConfig) {\n let RedisPresence: any = undefined;\n try {\n RedisPresence = require('@colyseus/redis-presence').RedisPresence;\n serverOptions.presence = new RedisPresence(process.env.REDIS_URI);\n } catch (e) {\n logger.warn(\"\");\n logger.warn(\"\u274C coult not initialize RedisPresence.\");\n logger.warn(\"\uD83D\uDC49 npm install --save @colyseus/redis-presence\");\n logger.warn(\"\");\n }\n }\n\n // force \"publicAddress\" when deployed on \"Colyseus Cloud\".\n serverOptions.publicAddress = process.env.SUBDOMAIN + \".\" + process.env.SERVER_NAME;\n\n // nginx is responsible for forwarding /{port}/ to this process\n if (useRedisConfig) {\n serverOptions.publicAddress += \"/\" + port;\n }\n }\n\n const transport = await getTransport(options);\n const gameServer = new Server({\n ...serverOptions,\n transport,\n });\n await options.initializeGameServer?.(gameServer);\n await options.beforeListen?.();\n\n\n if (process.env.COLYSEUS_CLOUD !== undefined) {\n // listening on socket\n // @ts-ignore\n await gameServer.listen(`/run/colyseus/${port}.sock`);\n\n } else {\n // listening on port\n await gameServer.listen(port);\n }\n\n // notify process manager (production)\n if (typeof(process.send) === \"function\") {\n process.send('ready');\n }\n\n if (options.displayLogs) {\n logger.info(`\u2694\uFE0F Listening on http://localhost:${port}`);\n }\n return gameServer;\n}\n\n\nexport async function getTransport(options: ConfigOptions) {\n let transport: Transport;\n\n if (!options.initializeTransport) {\n if (BunWebSockets !== undefined) {\n // @colyseus/bun-websockets\n options.initializeTransport = (options: any) => new BunWebSockets.BunWebSockets(options);\n\n } else {\n // use WebSocketTransport by default\n options.initializeTransport = (options: any) => new WebSocketTransport(options);\n }\n }\n\n let app: express.Express | undefined = express();\n let server = http.createServer(app);\n\n transport = await options.initializeTransport({ server });\n\n //\n // TODO: refactor me!\n // BunWebSockets: There's no need to instantiate \"app\" and \"server\" above\n //\n if (transport['expressApp']) {\n app = transport['expressApp'];\n }\n\n if (options.initializeExpress) {\n // uWebSockets.js + Express compatibility layer.\n // @ts-ignore\n if (transport['app']) {\n if (typeof (uWebSocketsExpressCompatibility) === \"function\") {\n if (options.displayLogs){\n logger.info(\"\u2705 uWebSockets.js + Express compatibility enabled\");\n }\n\n // @ts-ignore\n server = undefined;\n // @ts-ignore\n app = uWebSocketsExpressCompatibility(transport['app']);\n\n } else {\n if (options.displayLogs) {\n logger.warn(\"\");\n logger.warn(\"\u274C uWebSockets.js + Express compatibility mode couldn't be loaded, run the following command to fix:\");\n logger.warn(\"\uD83D\uDC49 npm install --save uwebsockets-express\");\n logger.warn(\"\");\n }\n app = undefined;\n }\n }\n }\n\n if (app) {\n // Enable CORS + JSON parsing.\n app.use(cors());\n app.use(express.json());\n\n if (options.initializeExpress) {\n await options.initializeExpress(app);\n }\n\n // health check for load balancers\n app.get(\"/__healthcheck\", (req, res) => {\n res.status(200).end();\n });\n\n app.get(\"/__cloudstats\", async (req, res) => {\n if (\n process.env.CLOUD_SECRET &&\n req.headers.authorization !== process.env.CLOUD_SECRET\n ) {\n res.status(401).end();\n return;\n }\n\n const roomCountPerProcess = await matchMaker.presence.hgetall(\"roomcount\");\n let rooms = 0;\n for (const processId in roomCountPerProcess) {\n rooms += Number(roomCountPerProcess[processId]);\n }\n\n const ccu = await matchMaker.stats.getGlobalCCU();\n const mem = await osUtils.mem.used();\n const cpu = (await osUtils.cpu.usage()) / 100;\n\n res.json({\n version: 1,\n mem: (mem.usedMemMb / mem.totalMemMb),\n cpu,\n ccu,\n rooms,\n });\n });\n\n if (options.displayLogs) {\n logger.info(\"\u2705 Express initialized\");\n }\n }\n\n return transport;\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["path", "envPath", "fs", "dotenv", "os", "options", "express", "http", "cors", "osUtils"]
7
7
  }
package/build/index.mjs CHANGED
@@ -166,6 +166,9 @@ async function getTransport(options) {
166
166
  if (options.initializeExpress) {
167
167
  await options.initializeExpress(app);
168
168
  }
169
+ app.get("/__healthcheck", (req, res) => {
170
+ res.status(200).end();
171
+ });
169
172
  app.get("/__cloudstats", async (req, res) => {
170
173
  if (process.env.CLOUD_SECRET && req.headers.authorization !== process.env.CLOUD_SECRET) {
171
174
  res.status(401).end();
@@ -176,7 +179,7 @@ async function getTransport(options) {
176
179
  for (const processId in roomCountPerProcess) {
177
180
  rooms += Number(roomCountPerProcess[processId]);
178
181
  }
179
- const ccu = await matchMaker.presence.get("_ccu");
182
+ const ccu = await matchMaker.stats.getGlobalCCU();
180
183
  const mem = await osUtils.mem.used();
181
184
  const cpu = await osUtils.cpu.usage() / 100;
182
185
  res.json({
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/index.ts"],
4
- "sourcesContent": ["import fs from \"fs\";\nimport os from \"os\";\nimport http from \"http\";\nimport path from \"path\";\nimport cors from \"cors\";\nimport express from \"express\";\nimport dotenv from \"dotenv\";\nimport osUtils from \"node-os-utils\";\nimport { logger, Server, ServerOptions, Transport, matchMaker } from '@colyseus/core';\nimport { WebSocketTransport } from '@colyseus/ws-transport';\n\n// try to import uWebSockets-express compatibility layer.\nlet uWebSocketsExpressCompatibility: any = undefined;\ntry { uWebSocketsExpressCompatibility = require('uwebsockets-express').default; } catch (e) {}\n\nlet BunWebSockets: any = undefined;\ntry { BunWebSockets = require('@colyseus/bun-websockets'); } catch (e) {}\n\nfunction getNodeEnv() {\n return process.env.NODE_ENV || \"development\";\n}\n\nfunction getRegion() {\n // EU, NA, AS, AF, AU, SA, UNKNOWN\n return (process.env.REGION || \"unknown\").toLowerCase();\n}\n\nfunction loadEnvFile(envFileOptions: string[], log: 'none' | 'success' | 'both' = 'none') {\n const envPaths = [];\n envFileOptions.forEach((envFilename) => {\n envPaths.push(path.resolve(path.dirname(require?.main?.filename || process.cwd()), \"..\", envFilename));\n envPaths.push(path.resolve(process.cwd(), envFilename));\n });\n\n // return the first .env path found\n const envPath = envPaths.find((envPath) => fs.existsSync(envPath));\n\n if (envPath) {\n dotenv.config({ path: envPath });\n\n if (log !== \"none\") {\n logger.info(`\u2705 ${path.basename(envPath)} loaded.`);\n }\n\n } else if (log === \"both\") {\n logger.info(`\u2139\uFE0F optional .env file not found: ${envFileOptions.join(\", \")}`);\n }\n}\n\n// load .env.cloud defined on admin panel\nif (process.env.COLYSEUS_CLOUD !== undefined) {\n loadEnvFile([`.env.cloud`]);\n}\n\n// (overrides previous env configs)\nloadEnvFile([`.env.${getNodeEnv()}`, `.env`], 'both');\n\nif (process.env.REGION !== undefined) {\n loadEnvFile([`.env.${getRegion()}.${getNodeEnv()}`], 'success');\n}\n\nexport interface ConfigOptions {\n options?: ServerOptions,\n displayLogs?: boolean,\n getId?: () => string,\n initializeTransport?: (options: any) => Transport,\n initializeExpress?: (app: express.Express) => void,\n initializeGameServer?: (app: Server) => void,\n beforeListen?: () => void,\n}\n\nconst ALLOWED_KEYS: { [key in keyof ConfigOptions]: string } = {\n 'displayLogs': \"boolean\",\n 'options': \"object\",\n 'getId': \"function\",\n 'initializeTransport': \"function\",\n 'initializeExpress': \"function\",\n 'initializeGameServer': \"function\",\n 'beforeListen': \"function\"\n};\n\nexport default function (options: ConfigOptions) {\n for (const option in options) {\n if (!ALLOWED_KEYS[option]) {\n throw new Error(`\u274C Invalid option '${option}'. Allowed options are: ${Object.keys(ALLOWED_KEYS).join(\", \")}`);\n }\n if(options[option] !== undefined && typeof(options[option]) !== ALLOWED_KEYS[option]) {\n throw new Error(`\u274C Invalid type for ${option}: please provide a ${ALLOWED_KEYS[option]} value.`);\n }\n }\n\n return options;\n}\n\n/**\n * Listen on your development environment\n * @param options Application options\n * @param port Port number to bind Colyseus + Express\n */\nexport async function listen(\n options: ConfigOptions,\n port: number = Number(process.env.PORT || 2567),\n) {\n const serverOptions = options.options || {};\n options.displayLogs = options.displayLogs ?? true;\n\n // Force 2567 port on Colyseus Cloud\n if (process.env.COLYSEUS_CLOUD !== undefined) {\n port = 2567;\n }\n\n //\n // Handling multiple processes\n // Use NODE_APP_INSTANCE to play nicely with pm2\n //\n const processNumber = Number(process.env.NODE_APP_INSTANCE || \"0\");\n port += processNumber;\n\n // automatically configure for production under Colyseus Cloud\n if (process.env.COLYSEUS_CLOUD !== undefined) {\n // special configuration is required when using multiple processes\n const useRedisConfig = (os.cpus().length > 1) || (process.env.REDIS_URI !== undefined);\n\n if (!serverOptions.driver && useRedisConfig) {\n let RedisDriver: any = undefined;\n try {\n RedisDriver = require('@colyseus/redis-driver').RedisDriver;\n serverOptions.driver = new RedisDriver(process.env.REDIS_URI);\n } catch (e) {\n logger.warn(\"\");\n logger.warn(\"\u274C coult not initialize RedisDriver.\");\n logger.warn(\"\uD83D\uDC49 npm install --save @colyseus/redis-driver\");\n logger.warn(\"\");\n }\n }\n\n if (!serverOptions.presence && useRedisConfig) {\n let RedisPresence: any = undefined;\n try {\n RedisPresence = require('@colyseus/redis-presence').RedisPresence;\n serverOptions.presence = new RedisPresence(process.env.REDIS_URI);\n } catch (e) {\n logger.warn(\"\");\n logger.warn(\"\u274C coult not initialize RedisPresence.\");\n logger.warn(\"\uD83D\uDC49 npm install --save @colyseus/redis-presence\");\n logger.warn(\"\");\n }\n }\n\n // force \"publicAddress\" when deployed on \"Colyseus Cloud\".\n serverOptions.publicAddress = process.env.SUBDOMAIN + \".\" + process.env.SERVER_NAME;\n\n // nginx is responsible for forwarding /{port}/ to this process\n if (useRedisConfig) {\n serverOptions.publicAddress += \"/\" + port;\n }\n }\n\n const transport = await getTransport(options);\n const gameServer = new Server({\n ...serverOptions,\n transport,\n });\n await options.initializeGameServer?.(gameServer);\n await options.beforeListen?.();\n\n\n if (process.env.COLYSEUS_CLOUD !== undefined) {\n // listening on socket\n // @ts-ignore\n await gameServer.listen(`/run/colyseus/${port}.sock`);\n\n } else {\n // listening on port\n await gameServer.listen(port);\n }\n\n // notify process manager (production)\n if (typeof(process.send) === \"function\") {\n process.send('ready');\n }\n\n if (options.displayLogs) {\n logger.info(`\u2694\uFE0F Listening on http://localhost:${port}`);\n }\n return gameServer;\n}\n\n\nexport async function getTransport(options: ConfigOptions) {\n let transport: Transport;\n\n if (!options.initializeTransport) {\n if (BunWebSockets !== undefined) {\n // @colyseus/bun-websockets\n options.initializeTransport = (options: any) => new BunWebSockets.BunWebSockets(options);\n\n } else {\n // use WebSocketTransport by default\n options.initializeTransport = (options: any) => new WebSocketTransport(options);\n }\n }\n\n let app: express.Express | undefined = express();\n let server = http.createServer(app);\n\n transport = await options.initializeTransport({ server });\n\n //\n // TODO: refactor me!\n // BunWebSockets: There's no need to instantiate \"app\" and \"server\" above\n //\n if (transport['expressApp']) {\n app = transport['expressApp'];\n }\n\n if (options.initializeExpress) {\n // uWebSockets.js + Express compatibility layer.\n // @ts-ignore\n if (transport['app']) {\n if (typeof (uWebSocketsExpressCompatibility) === \"function\") {\n if (options.displayLogs){\n logger.info(\"\u2705 uWebSockets.js + Express compatibility enabled\");\n }\n\n // @ts-ignore\n server = undefined;\n // @ts-ignore\n app = uWebSocketsExpressCompatibility(transport['app']);\n\n } else {\n if (options.displayLogs) {\n logger.warn(\"\");\n logger.warn(\"\u274C uWebSockets.js + Express compatibility mode couldn't be loaded, run the following command to fix:\");\n logger.warn(\"\uD83D\uDC49 npm install --save uwebsockets-express\");\n logger.warn(\"\");\n }\n app = undefined;\n }\n }\n }\n\n if (app) {\n // Enable CORS + JSON parsing.\n app.use(cors());\n app.use(express.json());\n\n if (options.initializeExpress) {\n await options.initializeExpress(app);\n }\n\n app.get(\"/__cloudstats\", async (req, res) => {\n if (\n process.env.CLOUD_SECRET &&\n req.headers.authorization !== process.env.CLOUD_SECRET\n ) {\n res.status(401).end();\n return;\n }\n\n const roomCountPerProcess = await matchMaker.presence.hgetall(\"roomcount\");\n let rooms = 0;\n for (const processId in roomCountPerProcess) {\n rooms += Number(roomCountPerProcess[processId]);\n }\n\n const ccu = await matchMaker.presence.get(\"_ccu\");\n const mem = await osUtils.mem.used();\n const cpu = (await osUtils.cpu.usage()) / 100;\n\n res.json({\n version: 1,\n mem: (mem.usedMemMb / mem.totalMemMb),\n cpu,\n ccu,\n rooms,\n });\n });\n\n if (options.displayLogs) {\n logger.info(\"\u2705 Express initialized\");\n }\n }\n\n return transport;\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import fs from \"fs\";\nimport os from \"os\";\nimport http from \"http\";\nimport path from \"path\";\nimport cors from \"cors\";\nimport express from \"express\";\nimport dotenv from \"dotenv\";\nimport osUtils from \"node-os-utils\";\nimport { logger, Server, ServerOptions, Transport, matchMaker } from '@colyseus/core';\nimport { WebSocketTransport } from '@colyseus/ws-transport';\n\n// try to import uWebSockets-express compatibility layer.\nlet uWebSocketsExpressCompatibility: any = undefined;\ntry { uWebSocketsExpressCompatibility = require('uwebsockets-express').default; } catch (e) {}\n\nlet BunWebSockets: any = undefined;\ntry { BunWebSockets = require('@colyseus/bun-websockets'); } catch (e) {}\n\nfunction getNodeEnv() {\n return process.env.NODE_ENV || \"development\";\n}\n\nfunction getRegion() {\n // EU, NA, AS, AF, AU, SA, UNKNOWN\n return (process.env.REGION || \"unknown\").toLowerCase();\n}\n\nfunction loadEnvFile(envFileOptions: string[], log: 'none' | 'success' | 'both' = 'none') {\n const envPaths = [];\n envFileOptions.forEach((envFilename) => {\n envPaths.push(path.resolve(path.dirname(require?.main?.filename || process.cwd()), \"..\", envFilename));\n envPaths.push(path.resolve(process.cwd(), envFilename));\n });\n\n // return the first .env path found\n const envPath = envPaths.find((envPath) => fs.existsSync(envPath));\n\n if (envPath) {\n dotenv.config({ path: envPath });\n\n if (log !== \"none\") {\n logger.info(`\u2705 ${path.basename(envPath)} loaded.`);\n }\n\n } else if (log === \"both\") {\n logger.info(`\u2139\uFE0F optional .env file not found: ${envFileOptions.join(\", \")}`);\n }\n}\n\n// load .env.cloud defined on admin panel\nif (process.env.COLYSEUS_CLOUD !== undefined) {\n loadEnvFile([`.env.cloud`]);\n}\n\n// (overrides previous env configs)\nloadEnvFile([`.env.${getNodeEnv()}`, `.env`], 'both');\n\nif (process.env.REGION !== undefined) {\n loadEnvFile([`.env.${getRegion()}.${getNodeEnv()}`], 'success');\n}\n\nexport interface ConfigOptions {\n options?: ServerOptions,\n displayLogs?: boolean,\n getId?: () => string,\n initializeTransport?: (options: any) => Transport,\n initializeExpress?: (app: express.Express) => void,\n initializeGameServer?: (app: Server) => void,\n beforeListen?: () => void,\n}\n\nconst ALLOWED_KEYS: { [key in keyof ConfigOptions]: string } = {\n 'displayLogs': \"boolean\",\n 'options': \"object\",\n 'getId': \"function\",\n 'initializeTransport': \"function\",\n 'initializeExpress': \"function\",\n 'initializeGameServer': \"function\",\n 'beforeListen': \"function\"\n};\n\nexport default function (options: ConfigOptions) {\n for (const option in options) {\n if (!ALLOWED_KEYS[option]) {\n throw new Error(`\u274C Invalid option '${option}'. Allowed options are: ${Object.keys(ALLOWED_KEYS).join(\", \")}`);\n }\n if(options[option] !== undefined && typeof(options[option]) !== ALLOWED_KEYS[option]) {\n throw new Error(`\u274C Invalid type for ${option}: please provide a ${ALLOWED_KEYS[option]} value.`);\n }\n }\n\n return options;\n}\n\n/**\n * Listen on your development environment\n * @param options Application options\n * @param port Port number to bind Colyseus + Express\n */\nexport async function listen(\n options: ConfigOptions,\n port: number = Number(process.env.PORT || 2567),\n) {\n const serverOptions = options.options || {};\n options.displayLogs = options.displayLogs ?? true;\n\n // Force 2567 port on Colyseus Cloud\n if (process.env.COLYSEUS_CLOUD !== undefined) {\n port = 2567;\n }\n\n //\n // Handling multiple processes\n // Use NODE_APP_INSTANCE to play nicely with pm2\n //\n const processNumber = Number(process.env.NODE_APP_INSTANCE || \"0\");\n port += processNumber;\n\n // automatically configure for production under Colyseus Cloud\n if (process.env.COLYSEUS_CLOUD !== undefined) {\n // special configuration is required when using multiple processes\n const useRedisConfig = (os.cpus().length > 1) || (process.env.REDIS_URI !== undefined);\n\n if (!serverOptions.driver && useRedisConfig) {\n let RedisDriver: any = undefined;\n try {\n RedisDriver = require('@colyseus/redis-driver').RedisDriver;\n serverOptions.driver = new RedisDriver(process.env.REDIS_URI);\n } catch (e) {\n logger.warn(\"\");\n logger.warn(\"\u274C coult not initialize RedisDriver.\");\n logger.warn(\"\uD83D\uDC49 npm install --save @colyseus/redis-driver\");\n logger.warn(\"\");\n }\n }\n\n if (!serverOptions.presence && useRedisConfig) {\n let RedisPresence: any = undefined;\n try {\n RedisPresence = require('@colyseus/redis-presence').RedisPresence;\n serverOptions.presence = new RedisPresence(process.env.REDIS_URI);\n } catch (e) {\n logger.warn(\"\");\n logger.warn(\"\u274C coult not initialize RedisPresence.\");\n logger.warn(\"\uD83D\uDC49 npm install --save @colyseus/redis-presence\");\n logger.warn(\"\");\n }\n }\n\n // force \"publicAddress\" when deployed on \"Colyseus Cloud\".\n serverOptions.publicAddress = process.env.SUBDOMAIN + \".\" + process.env.SERVER_NAME;\n\n // nginx is responsible for forwarding /{port}/ to this process\n if (useRedisConfig) {\n serverOptions.publicAddress += \"/\" + port;\n }\n }\n\n const transport = await getTransport(options);\n const gameServer = new Server({\n ...serverOptions,\n transport,\n });\n await options.initializeGameServer?.(gameServer);\n await options.beforeListen?.();\n\n\n if (process.env.COLYSEUS_CLOUD !== undefined) {\n // listening on socket\n // @ts-ignore\n await gameServer.listen(`/run/colyseus/${port}.sock`);\n\n } else {\n // listening on port\n await gameServer.listen(port);\n }\n\n // notify process manager (production)\n if (typeof(process.send) === \"function\") {\n process.send('ready');\n }\n\n if (options.displayLogs) {\n logger.info(`\u2694\uFE0F Listening on http://localhost:${port}`);\n }\n return gameServer;\n}\n\n\nexport async function getTransport(options: ConfigOptions) {\n let transport: Transport;\n\n if (!options.initializeTransport) {\n if (BunWebSockets !== undefined) {\n // @colyseus/bun-websockets\n options.initializeTransport = (options: any) => new BunWebSockets.BunWebSockets(options);\n\n } else {\n // use WebSocketTransport by default\n options.initializeTransport = (options: any) => new WebSocketTransport(options);\n }\n }\n\n let app: express.Express | undefined = express();\n let server = http.createServer(app);\n\n transport = await options.initializeTransport({ server });\n\n //\n // TODO: refactor me!\n // BunWebSockets: There's no need to instantiate \"app\" and \"server\" above\n //\n if (transport['expressApp']) {\n app = transport['expressApp'];\n }\n\n if (options.initializeExpress) {\n // uWebSockets.js + Express compatibility layer.\n // @ts-ignore\n if (transport['app']) {\n if (typeof (uWebSocketsExpressCompatibility) === \"function\") {\n if (options.displayLogs){\n logger.info(\"\u2705 uWebSockets.js + Express compatibility enabled\");\n }\n\n // @ts-ignore\n server = undefined;\n // @ts-ignore\n app = uWebSocketsExpressCompatibility(transport['app']);\n\n } else {\n if (options.displayLogs) {\n logger.warn(\"\");\n logger.warn(\"\u274C uWebSockets.js + Express compatibility mode couldn't be loaded, run the following command to fix:\");\n logger.warn(\"\uD83D\uDC49 npm install --save uwebsockets-express\");\n logger.warn(\"\");\n }\n app = undefined;\n }\n }\n }\n\n if (app) {\n // Enable CORS + JSON parsing.\n app.use(cors());\n app.use(express.json());\n\n if (options.initializeExpress) {\n await options.initializeExpress(app);\n }\n\n // health check for load balancers\n app.get(\"/__healthcheck\", (req, res) => {\n res.status(200).end();\n });\n\n app.get(\"/__cloudstats\", async (req, res) => {\n if (\n process.env.CLOUD_SECRET &&\n req.headers.authorization !== process.env.CLOUD_SECRET\n ) {\n res.status(401).end();\n return;\n }\n\n const roomCountPerProcess = await matchMaker.presence.hgetall(\"roomcount\");\n let rooms = 0;\n for (const processId in roomCountPerProcess) {\n rooms += Number(roomCountPerProcess[processId]);\n }\n\n const ccu = await matchMaker.stats.getGlobalCCU();\n const mem = await osUtils.mem.used();\n const cpu = (await osUtils.cpu.usage()) / 100;\n\n res.json({\n version: 1,\n mem: (mem.usedMemMb / mem.totalMemMb),\n cpu,\n ccu,\n rooms,\n });\n });\n\n if (options.displayLogs) {\n logger.info(\"\u2705 Express initialized\");\n }\n }\n\n return transport;\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["envPath", "options"]
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@colyseus/tools",
3
- "version": "0.15.20",
3
+ "version": "0.15.22",
4
4
  "description": "Colyseus Tools for Production",
5
5
  "input": "./src/index.ts",
6
6
  "main": "./build/index.js",
@@ -40,7 +40,7 @@
40
40
  "uwebsockets-express": "^1.1.10"
41
41
  },
42
42
  "dependencies": {
43
- "@colyseus/core": "^0.15.0",
43
+ "@colyseus/core": "^0.15.11",
44
44
  "@colyseus/ws-transport": "^0.15.0",
45
45
  "cors": "^2.8.5",
46
46
  "dotenv": "^8.2.0",
@@ -50,5 +50,5 @@
50
50
  "publishConfig": {
51
51
  "access": "public"
52
52
  },
53
- "gitHead": "53c870ed43c9a669cfd92b8f2bef2ee816a0add6"
53
+ "gitHead": "0089cc0070c1a51b2006eeb91a9cbc686abbdeb7"
54
54
  }