@babylonjs-toolkit/server 0.0.0-stage → 9.35.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.
Files changed (236) hide show
  1. package/CUSTOM.md +1690 -0
  2. package/DEPLOY.md +2012 -0
  3. package/README.md +1081 -2
  4. package/lib/AbuseLimits.d.ts +64 -0
  5. package/lib/AbuseLimits.js +121 -0
  6. package/lib/Authentication.d.ts +86 -0
  7. package/lib/Authentication.js +272 -0
  8. package/lib/BootSessionOwner.d.ts +86 -0
  9. package/lib/BootSessionOwner.js +116 -0
  10. package/lib/ColyseusLoggerAdapter.d.ts +32 -0
  11. package/lib/ColyseusLoggerAdapter.js +73 -0
  12. package/lib/DedicatedSceneRegistry.d.ts +52 -0
  13. package/lib/DedicatedSceneRegistry.js +74 -0
  14. package/lib/DedicatedSession.d.ts +152 -0
  15. package/lib/DedicatedSession.js +173 -0
  16. package/lib/DualTransport.d.ts +112 -0
  17. package/lib/DualTransport.js +197 -0
  18. package/lib/GameServer.d.ts +64 -0
  19. package/lib/GameServer.js +647 -0
  20. package/lib/GameServerConfig.d.ts +387 -0
  21. package/lib/GameServerConfig.js +1059 -0
  22. package/lib/GameServerLobbyRoom.d.ts +33 -0
  23. package/lib/GameServerLobbyRoom.js +56 -0
  24. package/lib/GameServerLogger.d.ts +111 -0
  25. package/lib/GameServerLogger.js +190 -0
  26. package/lib/GameServerMetrics.d.ts +158 -0
  27. package/lib/GameServerMetrics.js +276 -0
  28. package/lib/GameServerState.d.ts +164 -0
  29. package/lib/GameServerState.js +26 -0
  30. package/lib/HeadlessRuntime.d.ts +316 -0
  31. package/lib/HeadlessRuntime.js +380 -0
  32. package/lib/JoinGate.d.ts +34 -0
  33. package/lib/JoinGate.js +221 -0
  34. package/lib/NetworkAddresses.d.ts +33 -0
  35. package/lib/NetworkAddresses.js +90 -0
  36. package/lib/PlayerTokens.d.ts +17 -0
  37. package/lib/PlayerTokens.js +24 -0
  38. package/lib/RoomServerTransport.d.ts +73 -0
  39. package/lib/RoomServerTransport.js +90 -0
  40. package/lib/ServerEndpoints.d.ts +133 -0
  41. package/lib/ServerEndpoints.js +247 -0
  42. package/lib/ServerInit.d.ts +28 -0
  43. package/lib/ServerInit.js +113 -0
  44. package/lib/SessionRoom.d.ts +391 -0
  45. package/lib/SessionRoom.js +930 -0
  46. package/lib/TlsCertificates.d.ts +35 -0
  47. package/lib/TlsCertificates.js +130 -0
  48. package/lib/admin/AccountRoutes.d.ts +8 -0
  49. package/lib/admin/AccountRoutes.js +502 -0
  50. package/lib/admin/AdminAccounts.d.ts +329 -0
  51. package/lib/admin/AdminAccounts.js +607 -0
  52. package/lib/admin/AdminApiRouter.d.ts +202 -0
  53. package/lib/admin/AdminApiRouter.js +465 -0
  54. package/lib/admin/AdminApiTypes.d.ts +1782 -0
  55. package/lib/admin/AdminApiTypes.js +4 -0
  56. package/lib/admin/AdminAudit.d.ts +113 -0
  57. package/lib/admin/AdminAudit.js +266 -0
  58. package/lib/admin/AdminCli.d.ts +7 -0
  59. package/lib/admin/AdminCli.js +351 -0
  60. package/lib/admin/AdminClock.d.ts +51 -0
  61. package/lib/admin/AdminClock.js +10 -0
  62. package/lib/admin/AdminConsole.d.ts +39 -0
  63. package/lib/admin/AdminConsole.js +325 -0
  64. package/lib/admin/AdminConstants.d.ts +147 -0
  65. package/lib/admin/AdminConstants.js +167 -0
  66. package/lib/admin/AdminCrypto.d.ts +19 -0
  67. package/lib/admin/AdminCrypto.js +29 -0
  68. package/lib/admin/AdminExtensionsHost.d.ts +176 -0
  69. package/lib/admin/AdminExtensionsHost.js +307 -0
  70. package/lib/admin/AdminPasswords.d.ts +33 -0
  71. package/lib/admin/AdminPasswords.js +92 -0
  72. package/lib/admin/AdminPermissions.d.ts +28 -0
  73. package/lib/admin/AdminPermissions.js +74 -0
  74. package/lib/admin/AdminRecords.d.ts +196 -0
  75. package/lib/admin/AdminRecords.js +3 -0
  76. package/lib/admin/AdminRequestBodies.d.ts +47 -0
  77. package/lib/admin/AdminRequestBodies.js +84 -0
  78. package/lib/admin/AdminRequestGate.d.ts +38 -0
  79. package/lib/admin/AdminRequestGate.js +59 -0
  80. package/lib/admin/AdminResponses.d.ts +103 -0
  81. package/lib/admin/AdminResponses.js +164 -0
  82. package/lib/admin/AdminServices.d.ts +99 -0
  83. package/lib/admin/AdminServices.js +4 -0
  84. package/lib/admin/AdminStaticFiles.d.ts +29 -0
  85. package/lib/admin/AdminStaticFiles.js +97 -0
  86. package/lib/admin/AdminStore.d.ts +152 -0
  87. package/lib/admin/AdminStore.js +46 -0
  88. package/lib/admin/AlertChannels.d.ts +43 -0
  89. package/lib/admin/AlertChannels.js +120 -0
  90. package/lib/admin/AlertEngine.d.ts +231 -0
  91. package/lib/admin/AlertEngine.js +681 -0
  92. package/lib/admin/AlertRoutes.d.ts +8 -0
  93. package/lib/admin/AlertRoutes.js +180 -0
  94. package/lib/admin/ApiKeyRoutes.d.ts +8 -0
  95. package/lib/admin/ApiKeyRoutes.js +53 -0
  96. package/lib/admin/ApiKeys.d.ts +63 -0
  97. package/lib/admin/ApiKeys.js +167 -0
  98. package/lib/admin/AuditRoutes.d.ts +8 -0
  99. package/lib/admin/AuditRoutes.js +106 -0
  100. package/lib/admin/AuthToolRoutes.d.ts +13 -0
  101. package/lib/admin/AuthToolRoutes.js +164 -0
  102. package/lib/admin/BanList.d.ts +87 -0
  103. package/lib/admin/BanList.js +152 -0
  104. package/lib/admin/CborDecoder.d.ts +18 -0
  105. package/lib/admin/CborDecoder.js +201 -0
  106. package/lib/admin/ColyseusCloudClient.d.ts +313 -0
  107. package/lib/admin/ColyseusCloudClient.js +272 -0
  108. package/lib/admin/ColyseusCloudRoutes.d.ts +8 -0
  109. package/lib/admin/ColyseusCloudRoutes.js +91 -0
  110. package/lib/admin/ColyseusCloudService.d.ts +180 -0
  111. package/lib/admin/ColyseusCloudService.js +476 -0
  112. package/lib/admin/ColyseusCloudSettings.d.ts +16 -0
  113. package/lib/admin/ColyseusCloudSettings.js +29 -0
  114. package/lib/admin/ColyseusCloudViews.d.ts +105 -0
  115. package/lib/admin/ColyseusCloudViews.js +371 -0
  116. package/lib/admin/CommonPasswords.d.ts +6 -0
  117. package/lib/admin/CommonPasswords.js +19 -0
  118. package/lib/admin/ConfigOverrides.d.ts +174 -0
  119. package/lib/admin/ConfigOverrides.js +406 -0
  120. package/lib/admin/ConfigRoutes.d.ts +8 -0
  121. package/lib/admin/ConfigRoutes.js +91 -0
  122. package/lib/admin/ConsoleSessions.d.ts +112 -0
  123. package/lib/admin/ConsoleSessions.js +201 -0
  124. package/lib/admin/DedicatedRoutes.d.ts +21 -0
  125. package/lib/admin/DedicatedRoutes.js +254 -0
  126. package/lib/admin/ExtensionRoutes.d.ts +8 -0
  127. package/lib/admin/ExtensionRoutes.js +145 -0
  128. package/lib/admin/FileAdminStore.d.ts +157 -0
  129. package/lib/admin/FileAdminStore.js +349 -0
  130. package/lib/admin/FleetDirectory.d.ts +323 -0
  131. package/lib/admin/FleetDirectory.js +489 -0
  132. package/lib/admin/FleetLeader.d.ts +43 -0
  133. package/lib/admin/FleetLeader.js +89 -0
  134. package/lib/admin/FleetRoutes.d.ts +55 -0
  135. package/lib/admin/FleetRoutes.js +465 -0
  136. package/lib/admin/HealthWarnings.d.ts +10 -0
  137. package/lib/admin/HealthWarnings.js +95 -0
  138. package/lib/admin/LeaderboardRoutes.d.ts +8 -0
  139. package/lib/admin/LeaderboardRoutes.js +569 -0
  140. package/lib/admin/LogBuffer.d.ts +60 -0
  141. package/lib/admin/LogBuffer.js +92 -0
  142. package/lib/admin/LogRedaction.d.ts +15 -0
  143. package/lib/admin/LogRedaction.js +72 -0
  144. package/lib/admin/LogRoutes.d.ts +45 -0
  145. package/lib/admin/LogRoutes.js +307 -0
  146. package/lib/admin/MaintenanceMode.d.ts +41 -0
  147. package/lib/admin/MaintenanceMode.js +74 -0
  148. package/lib/admin/MaintenanceWindows.d.ts +91 -0
  149. package/lib/admin/MaintenanceWindows.js +207 -0
  150. package/lib/admin/MetricsRoutes.d.ts +8 -0
  151. package/lib/admin/MetricsRoutes.js +209 -0
  152. package/lib/admin/MetricsSampler.d.ts +124 -0
  153. package/lib/admin/MetricsSampler.js +211 -0
  154. package/lib/admin/OneTimeCodes.d.ts +60 -0
  155. package/lib/admin/OneTimeCodes.js +162 -0
  156. package/lib/admin/OpenIdConnect.d.ts +146 -0
  157. package/lib/admin/OpenIdConnect.js +335 -0
  158. package/lib/admin/Passkeys.d.ts +130 -0
  159. package/lib/admin/Passkeys.js +432 -0
  160. package/lib/admin/PlayerRoutes.d.ts +20 -0
  161. package/lib/admin/PlayerRoutes.js +676 -0
  162. package/lib/admin/RedisAdminStore.d.ts +114 -0
  163. package/lib/admin/RedisAdminStore.js +258 -0
  164. package/lib/admin/RolloutCoordinator.d.ts +99 -0
  165. package/lib/admin/RolloutCoordinator.js +321 -0
  166. package/lib/admin/ServerEvents.d.ts +57 -0
  167. package/lib/admin/ServerEvents.js +89 -0
  168. package/lib/admin/SessionRoutes.d.ts +113 -0
  169. package/lib/admin/SessionRoutes.js +386 -0
  170. package/lib/admin/UserRoutes.d.ts +8 -0
  171. package/lib/admin/UserRoutes.js +214 -0
  172. package/lib/cli.d.ts +2 -0
  173. package/lib/cli.js +221 -0
  174. package/lib/console/assets/index-CI5N7c-T.js +21 -0
  175. package/lib/console/assets/index-DPitvzLp.css +1 -0
  176. package/lib/console/favicon.svg +1 -0
  177. package/lib/console/index.html +16 -0
  178. package/lib/discord/DiscordOAuth.d.ts +57 -0
  179. package/lib/discord/DiscordOAuth.js +127 -0
  180. package/lib/discord/DiscordSessions.d.ts +79 -0
  181. package/lib/discord/DiscordSessions.js +135 -0
  182. package/lib/discord/DiscordSignInConstants.d.ts +54 -0
  183. package/lib/discord/DiscordSignInConstants.js +55 -0
  184. package/lib/discord/DiscordSignInRoutes.d.ts +51 -0
  185. package/lib/discord/DiscordSignInRoutes.js +359 -0
  186. package/lib/index.d.ts +24 -0
  187. package/lib/index.js +18 -0
  188. package/lib/leaderboards/FileLeaderboardRankStore.d.ts +293 -0
  189. package/lib/leaderboards/FileLeaderboardRankStore.js +808 -0
  190. package/lib/leaderboards/LeaderboardConstants.d.ts +63 -0
  191. package/lib/leaderboards/LeaderboardConstants.js +70 -0
  192. package/lib/leaderboards/LeaderboardError.d.ts +15 -0
  193. package/lib/leaderboards/LeaderboardError.js +20 -0
  194. package/lib/leaderboards/LeaderboardIdentity.d.ts +44 -0
  195. package/lib/leaderboards/LeaderboardIdentity.js +72 -0
  196. package/lib/leaderboards/LeaderboardPublicApi.d.ts +17 -0
  197. package/lib/leaderboards/LeaderboardPublicApi.js +389 -0
  198. package/lib/leaderboards/LeaderboardRankStore.d.ts +296 -0
  199. package/lib/leaderboards/LeaderboardRankStore.js +18 -0
  200. package/lib/leaderboards/LeaderboardRules.d.ts +122 -0
  201. package/lib/leaderboards/LeaderboardRules.js +472 -0
  202. package/lib/leaderboards/LeaderboardScheduler.d.ts +43 -0
  203. package/lib/leaderboards/LeaderboardScheduler.js +103 -0
  204. package/lib/leaderboards/LeaderboardService.d.ts +669 -0
  205. package/lib/leaderboards/LeaderboardService.js +1667 -0
  206. package/lib/leaderboards/LeaderboardTransfer.d.ts +35 -0
  207. package/lib/leaderboards/LeaderboardTransfer.js +580 -0
  208. package/lib/leaderboards/RedisLeaderboardRankStore.d.ts +282 -0
  209. package/lib/leaderboards/RedisLeaderboardRankStore.js +691 -0
  210. package/package.json +64 -4
  211. package/templates/init/Caddyfile +6 -0
  212. package/templates/init/DEPLOY.md +233 -0
  213. package/templates/init/Dockerfile +12 -0
  214. package/templates/init/app.json +21 -0
  215. package/templates/init/aws/README.md +118 -0
  216. package/templates/init/aws/ecs-fargate-alb.yml +207 -0
  217. package/templates/init/aws/ecs-fargate-nlb-quic.yml +210 -0
  218. package/templates/init/babylon-game-server.config.mjs +158 -0
  219. package/templates/init/colyseus-cloud/README.md +133 -0
  220. package/templates/init/colyseus-cloud/babylon-game-server.config.mjs +36 -0
  221. package/templates/init/colyseus-cloud/ecosystem.config.cjs +35 -0
  222. package/templates/init/colyseus-cloud/gitignore +6 -0
  223. package/templates/init/colyseus-cloud/package.json +15 -0
  224. package/templates/init/digitalocean-app.yaml +30 -0
  225. package/templates/init/docker-compose.full.yml +45 -0
  226. package/templates/init/docker-compose.websocket.yml +41 -0
  227. package/templates/init/fly.toml +56 -0
  228. package/templates/init/heroku.yml +11 -0
  229. package/templates/init/kubernetes/deployment.yaml +71 -0
  230. package/templates/init/kubernetes/redis.yaml +73 -0
  231. package/templates/init/kubernetes/service.yaml +24 -0
  232. package/templates/init/monitoring/grafana-dashboard.json +539 -0
  233. package/templates/init/monitoring/prometheus-alerts.yml +51 -0
  234. package/templates/init/monitoring/prometheus-scrape.yml +17 -0
  235. package/templates/init/railway.json +13 -0
  236. package/templates/init/render.yaml +19 -0
package/lib/cli.js ADDED
@@ -0,0 +1,221 @@
1
+ #!/usr/bin/env node
2
+ import http from "node:http";
3
+ import https from "node:https";
4
+ import { createGameServer } from "./GameServer.js";
5
+ import { GameServerConfigError, isProductionEnvironment, loadGameServerConfig, loadGameServerConfigWithSources } from "./GameServerConfig.js";
6
+ import { getLogger } from "./GameServerLogger.js";
7
+ import { readPackageVersion, writeRecipes } from "./ServerInit.js";
8
+ import { runAdminCommand } from "./admin/AdminCli.js";
9
+ /** Exit code of a configuration problem. */
10
+ const CONFIG_PROBLEM_EXIT_CODE = 2;
11
+ /** Exit code of any other startup failure. */
12
+ const STARTUP_FAILURE_EXIT_CODE = 1;
13
+ /** The default subcommand. */
14
+ const START_COMMAND = "start";
15
+ /** The subcommand that writes the starter folder (config, env, Dockerfile and deployment recipes). */
16
+ const INIT_COMMAND = "init";
17
+ /** The folder `init` writes when none is named. */
18
+ const DEFAULT_INIT_FOLDER = "./babylon-game-server";
19
+ /** The flag that lets `init` overwrite existing files. */
20
+ const FORCE_FLAG = "--force";
21
+ /** Exit code of an `init` that left existing files alone. */
22
+ const FILES_SKIPPED_EXIT_CODE = 1;
23
+ /** The subcommand that manages admin accounts and API keys on the admin data store (game-server-admin-console T3). */
24
+ const ADMIN_COMMAND = "admin";
25
+ /** The subcommand that checks a running server's health (the Docker HEALTHCHECK). */
26
+ const HEALTHCHECK_COMMAND = "healthcheck";
27
+ /** Exit code of a healthy server. */
28
+ const HEALTHY_EXIT_CODE = 0;
29
+ /** Exit code of an unhealthy or unreachable server (Docker reserves 2, so every failure uses 1). */
30
+ const UNHEALTHY_EXIT_CODE = 1;
31
+ /** Milliseconds the health check waits for an answer. */
32
+ const HEALTHCHECK_TIMEOUT_MS = 3000;
33
+ /** The health endpoint the check calls (ServerEndpoints). */
34
+ const HEALTH_PATH = "/game-server/health";
35
+ /** The address the check calls: the server's own loopback interface. */
36
+ const HEALTHCHECK_HOST = "127.0.0.1";
37
+ /** HTTP status of a healthy answer. */
38
+ const HTTP_OK = 200;
39
+ /** Bind addresses that only accept connections from this machine. */
40
+ const LOOPBACK_HOSTS = ["localhost", "127.0.0.1", "::1"];
41
+ /**
42
+ * How the banner names the TLS setup.
43
+ * @param tls The TLS settings.
44
+ * @returns "off", "on (files)", "on (pem)" or "on (development)".
45
+ */
46
+ function describeTls(tls) {
47
+ if (!tls.enabled)
48
+ return "off";
49
+ if (tls.certFile != null && tls.keyFile != null)
50
+ return "on (files)";
51
+ if (tls.certPem != null && tls.keyPem != null)
52
+ return "on (pem)";
53
+ return "on (development)";
54
+ }
55
+ /**
56
+ * Prints the startup banner (§Control flow). It is plain console text in every log format, so platforms show it.
57
+ * @param running The running server.
58
+ */
59
+ function printBanner(running) {
60
+ const config = running.config;
61
+ const authText = config.auth.enabled ? config.auth.mode : "off";
62
+ console.log("Babylon Game Server " + readPackageVersion() + " listening on " + running.urls.webSocket);
63
+ console.log(" HTTP: " + running.urls.http);
64
+ console.log(" WebTransport: " + (running.urls.webTransport ?? "off"));
65
+ console.log(" TLS: " + describeTls(config.tls) + " UDP: " + describeUdp(running) + " Auth: " + authText + " Redis: " + describeRedis(config.redis.url));
66
+ }
67
+ /**
68
+ * How the banner names the Redis setup, without credentials.
69
+ * @param redisUrl The configured Redis URL, or null.
70
+ * @returns "off", or "on (<host>:<port>)".
71
+ */
72
+ function describeRedis(redisUrl) {
73
+ if (redisUrl == null)
74
+ return "off";
75
+ try {
76
+ return "on (" + new URL(redisUrl).host + ")";
77
+ }
78
+ catch {
79
+ return "on";
80
+ }
81
+ }
82
+ /**
83
+ * How the banner names the UDP setup.
84
+ * @param running The running server.
85
+ * @returns "off", or "on (WebTransport on <url>, UDP <port>)".
86
+ */
87
+ function describeUdp(running) {
88
+ if (running.urls.webTransport == null)
89
+ return "off";
90
+ return "on (WebTransport on " + running.urls.webTransport + ", UDP " + running.port + ")";
91
+ }
92
+ /**
93
+ * Warns when a production server accepts anyone: auth off on an address other machines can reach (D2).
94
+ * @param config The config.
95
+ * @param environment The environment the config was loaded from.
96
+ */
97
+ function warnWhenOpenInProduction(config, environment) {
98
+ const isLoopback = LOOPBACK_HOSTS.includes(config.host) || config.host.startsWith("127.");
99
+ if (!isProductionEnvironment(environment) || config.auth.enabled || isLoopback)
100
+ return;
101
+ getLogger().warn("auth is disabled and the server listens on " + config.host + ": anyone who can reach it can join (set GAME_SERVER_AUTH_ENABLED)");
102
+ }
103
+ /**
104
+ * Prints every configuration problem to stderr.
105
+ * @param error The configuration error.
106
+ */
107
+ function printConfigProblems(error) {
108
+ console.error("Babylon Game Server configuration problems:");
109
+ for (const problem of error.problems)
110
+ console.error(" - " + problem);
111
+ }
112
+ /**
113
+ * `babylon-game-server [start] [flags]`: loads the config (defaults < Colyseus Cloud's defaults on that host < file < env < flags), starts the server (which
114
+ * starts its boot dedicated sessions), and prints the banner.
115
+ * @param argumentList The arguments after the subcommand.
116
+ * @param environment The process environment.
117
+ */
118
+ async function runStart(argumentList, environment) {
119
+ const loaded = await loadGameServerConfigWithSources({ argv: argumentList, environment: environment, workingDirectory: process.cwd() });
120
+ const config = loaded.config;
121
+ const running = await createGameServer({ config: config, handleSignals: true, configSources: loaded.sources });
122
+ printBanner(running);
123
+ warnWhenOpenInProduction(config, environment);
124
+ }
125
+ /**
126
+ * `babylon-game-server healthcheck [flags]`: loads the same config the server uses and GETs its own
127
+ * `/game-server/health` on 127.0.0.1 over the configured scheme (TLS certificates are not checked: the call never
128
+ * leaves the machine). Sets exit code 0 on HTTP 200 and 1 on anything else, including a config problem, so Docker's
129
+ * HEALTHCHECK can run it.
130
+ * @param argumentList The arguments after the subcommand.
131
+ * @param environment The process environment.
132
+ */
133
+ async function runHealthcheck(argumentList, environment) {
134
+ let config;
135
+ try {
136
+ config = await loadGameServerConfig({ argv: argumentList, environment: environment, workingDirectory: process.cwd() });
137
+ }
138
+ catch (error) {
139
+ if (error instanceof GameServerConfigError)
140
+ printConfigProblems(error);
141
+ else
142
+ console.error(error);
143
+ process.exitCode = UNHEALTHY_EXIT_CODE;
144
+ return;
145
+ }
146
+ const status = await requestHealthStatus(config.port, config.tls.enabled);
147
+ process.exitCode = (status === HTTP_OK) ? HEALTHY_EXIT_CODE : UNHEALTHY_EXIT_CODE;
148
+ }
149
+ /**
150
+ * GETs the health endpoint of the server on this machine.
151
+ * @param port The server port.
152
+ * @param secure True for https (certificates are not checked).
153
+ * @returns The HTTP status, or null when the server did not answer within HEALTHCHECK_TIMEOUT_MS.
154
+ */
155
+ function requestHealthStatus(port, secure) {
156
+ return new Promise((resolve) => {
157
+ const scheme = secure ? "https" : "http";
158
+ const url = scheme + "://" + HEALTHCHECK_HOST + ":" + port + HEALTH_PATH;
159
+ const handleResponse = (response) => {
160
+ response.resume();
161
+ resolve(response.statusCode ?? null);
162
+ };
163
+ const request = secure
164
+ ? https.get(url, { timeout: HEALTHCHECK_TIMEOUT_MS, rejectUnauthorized: false }, handleResponse)
165
+ : http.get(url, { timeout: HEALTHCHECK_TIMEOUT_MS }, handleResponse);
166
+ request.on("timeout", () => request.destroy());
167
+ request.on("error", () => resolve(null));
168
+ });
169
+ }
170
+ /**
171
+ * `babylon-game-server init [folder] [--force]`: writes the starter folder (D27) and prints each file and the next step.
172
+ * Existing files are kept unless `--force`; each one is listed as `skipped (exists): <path>` and the exit code is 1.
173
+ * @param argumentList The arguments after the subcommand.
174
+ */
175
+ async function runInit(argumentList) {
176
+ const force = argumentList.includes(FORCE_FLAG);
177
+ const folder = argumentList.find((argument) => !argument.startsWith("--")) ?? DEFAULT_INIT_FOLDER;
178
+ const result = await writeRecipes(folder, force);
179
+ for (const filePath of result.written)
180
+ console.log("wrote " + filePath);
181
+ for (const filePath of result.skipped)
182
+ console.log("skipped (exists): " + filePath);
183
+ if (result.written.length > 0) {
184
+ console.log("Edit babylon-game-server.config.mjs, then see DEPLOY.md");
185
+ console.log("Recommended host: Colyseus Cloud. Its deploy repository is colyseus-cloud/; see colyseus-cloud/README.md");
186
+ }
187
+ if (result.skipped.length > 0) {
188
+ console.log("Run again with " + FORCE_FLAG + " to overwrite the skipped files.");
189
+ process.exitCode = FILES_SKIPPED_EXIT_CODE;
190
+ }
191
+ }
192
+ /**
193
+ * Runs the subcommand the command line names (`start` when the first argument is a flag or absent).
194
+ * @param argumentList The command-line arguments after the script name.
195
+ * @param environment The process environment.
196
+ */
197
+ async function main(argumentList, environment) {
198
+ const command = argumentList[0];
199
+ if (command === INIT_COMMAND) {
200
+ await runInit(argumentList.slice(1));
201
+ return;
202
+ }
203
+ if (command === ADMIN_COMMAND) {
204
+ await runAdminCommand(argumentList.slice(1), environment);
205
+ return;
206
+ }
207
+ if (command === HEALTHCHECK_COMMAND) {
208
+ await runHealthcheck(argumentList.slice(1), environment);
209
+ return;
210
+ }
211
+ const namesStart = command === START_COMMAND;
212
+ await runStart(namesStart ? argumentList.slice(1) : argumentList, environment);
213
+ }
214
+ main(process.argv.slice(2), process.env).catch((error) => {
215
+ if (error instanceof GameServerConfigError) {
216
+ printConfigProblems(error);
217
+ process.exit(CONFIG_PROBLEM_EXIT_CODE);
218
+ }
219
+ console.error(error);
220
+ process.exitCode = STARTUP_FAILURE_EXIT_CODE;
221
+ });