@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
@@ -0,0 +1,313 @@
1
+ import type { CloudHistoryResolution, CloudLogLines, CloudLogStream, CloudProblemView } from "./AdminApiTypes.js";
2
+ /** A region of a Cloud location. */
3
+ export interface CloudApiRegion {
4
+ code: string;
5
+ city: string;
6
+ country: string;
7
+ }
8
+ /** A location's plan. */
9
+ export interface CloudApiPlan {
10
+ vcpus: number;
11
+ ram_mb: number;
12
+ transfer_gb: number;
13
+ }
14
+ /** An instance in GET /applications. */
15
+ export interface CloudApiInstance {
16
+ id: number;
17
+ endpoint: string | null;
18
+ status: string;
19
+ deploy_status: string | null;
20
+ deployed_at: string | null;
21
+ }
22
+ /** A location in GET /applications. */
23
+ export interface CloudApiLocation {
24
+ id: number;
25
+ region: CloudApiRegion;
26
+ status: string;
27
+ scale_strategy: string;
28
+ endpoint: string | null;
29
+ plan: CloudApiPlan;
30
+ instances: CloudApiInstance[];
31
+ }
32
+ /** An application in GET /applications. */
33
+ export interface CloudApiApplication {
34
+ id: number;
35
+ slug: string;
36
+ name: string;
37
+ maintenance_mode: boolean;
38
+ created_at: string;
39
+ locations: CloudApiLocation[];
40
+ }
41
+ /** Load figures of a total or a history point. */
42
+ export interface CloudApiTotals {
43
+ ccu: number;
44
+ rooms: number;
45
+ cpu_percent: number;
46
+ memory_percent: number;
47
+ }
48
+ /** A process in GET /metrics/current. */
49
+ export interface CloudApiProcess {
50
+ id: number;
51
+ status: string;
52
+ started_at: string | null;
53
+ restarts: number;
54
+ cpu_percent: number;
55
+ memory_mb: number;
56
+ ccu: number;
57
+ rooms: number;
58
+ node_version: string;
59
+ }
60
+ /** An instance sample in GET /metrics/current (values null when silent). */
61
+ export interface CloudApiInstanceSample {
62
+ id: number;
63
+ sampled_at: string | null;
64
+ ccu: number | null;
65
+ rooms: number | null;
66
+ cpu_percent: number | null;
67
+ memory_percent: number | null;
68
+ processes: CloudApiProcess[];
69
+ }
70
+ /** A location in GET /metrics/current. */
71
+ export interface CloudApiLocationMetrics {
72
+ id: number;
73
+ region: string;
74
+ totals: CloudApiTotals | null;
75
+ instances: CloudApiInstanceSample[];
76
+ }
77
+ /** GET /applications/{slug}/metrics/current. */
78
+ export interface CloudApiCurrentMetrics {
79
+ application: string;
80
+ window_minutes: number;
81
+ locations: CloudApiLocationMetrics[];
82
+ }
83
+ /** A point in GET /metrics. */
84
+ export interface CloudApiHistoryPoint extends CloudApiTotals {
85
+ time: string;
86
+ }
87
+ /** A location in GET /metrics. */
88
+ export interface CloudApiLocationHistory {
89
+ id: number;
90
+ region: string;
91
+ points: CloudApiHistoryPoint[];
92
+ }
93
+ /** GET /applications/{slug}/metrics. */
94
+ export interface CloudApiHistory {
95
+ application: string;
96
+ resolution: CloudHistoryResolution;
97
+ from: string;
98
+ to: string;
99
+ locations: CloudApiLocationHistory[];
100
+ }
101
+ /** A day in GET /egress. */
102
+ export interface CloudApiEgressDay {
103
+ date: string;
104
+ outgoing_bytes: number;
105
+ incoming_bytes: number;
106
+ }
107
+ /** A location in GET /egress. */
108
+ export interface CloudApiLocationEgress {
109
+ id: number;
110
+ region: string;
111
+ outgoing_bytes: number;
112
+ incoming_bytes: number;
113
+ days: CloudApiEgressDay[];
114
+ }
115
+ /** GET /applications/{slug}/egress. */
116
+ export interface CloudApiEgress {
117
+ application: string;
118
+ from: string;
119
+ to: string;
120
+ collected_at: string | null;
121
+ locations: CloudApiLocationEgress[];
122
+ }
123
+ /** A deploy in GET /deploys. */
124
+ export interface CloudApiDeploy {
125
+ id: number;
126
+ status: string;
127
+ branch: string;
128
+ commit: string | null;
129
+ message: string | null;
130
+ started_at: string;
131
+ finished_at: string | null;
132
+ }
133
+ /** GET /deploys/{id} data. */
134
+ export interface CloudApiDeployDetail extends CloudApiDeploy {
135
+ output: string | null;
136
+ }
137
+ /** The billing account in GET /billing. */
138
+ export interface CloudApiAccount {
139
+ currency: string;
140
+ credit_balance: number;
141
+ balance_due: number;
142
+ unused_time_credit: number;
143
+ }
144
+ /** A subscription in GET /billing. */
145
+ export interface CloudApiSubscription {
146
+ status: string;
147
+ monthly_price: number;
148
+ current_period_end: string;
149
+ cancel_at_period_end: boolean;
150
+ }
151
+ /** An application in GET /billing. */
152
+ export interface CloudApiBillingApplication {
153
+ id: number;
154
+ slug: string;
155
+ name: string;
156
+ subscription: CloudApiSubscription | null;
157
+ }
158
+ /** GET /billing. */
159
+ export interface CloudApiBilling {
160
+ account: CloudApiAccount | null;
161
+ applications: CloudApiBillingApplication[];
162
+ fetched_at: string;
163
+ }
164
+ /** A Colyseus Cloud API failure: a non-2xx answer (plain-text proxy errors included) or no answer at all. */
165
+ export declare class ColyseusCloudApiError extends Error {
166
+ /** HTTP status, or 0 when Colyseus did not answer. */
167
+ readonly status: number;
168
+ /** Colyseus's error code, or one derived from the status ("rate_limited", "unavailable", "server_error", "invalid_request", "unreachable"). */
169
+ readonly code: string;
170
+ /** Seconds to wait before retrying (429, 5xx and no answer), or null when retrying sooner will not help. */
171
+ readonly retryAfterSeconds: number | null;
172
+ /**
173
+ * Creates the error.
174
+ * @param status HTTP status, or 0 for no answer.
175
+ * @param code Stable error code.
176
+ * @param message Human-readable explanation (never contains the token).
177
+ * @param retryAfterSeconds Seconds to wait, or null.
178
+ */
179
+ constructor(status: number, code: string, message: string, retryAfterSeconds: number | null);
180
+ /**
181
+ * The error as the console shows it.
182
+ * @returns The problem view.
183
+ */
184
+ toProblem(): CloudProblemView;
185
+ }
186
+ /**
187
+ * Seconds to wait after a failed answer (Colyseus's polling guide): Retry-After for 429 and 5xx, at least
188
+ * COLYSEUS_CLOUD_MIN_RETRY_SECONDS, COLYSEUS_CLOUD_DEFAULT_RETRY_SECONDS when missing or not a number; null otherwise.
189
+ * @param status The HTTP status.
190
+ * @param retryAfterHeader The Retry-After header, or null.
191
+ * @returns Seconds, or null.
192
+ */
193
+ export declare function retryAfterSecondsOf(status: number, retryAfterHeader: string | null): number | null;
194
+ /**
195
+ * The error of a non-2xx answer: Colyseus's JSON code and message when present, else the plain text with a code from
196
+ * the status (429 "rate_limited", 502/503/504 "unavailable", other 5xx "server_error", else "invalid_request").
197
+ * @param response The failed answer.
198
+ * @returns The error.
199
+ */
200
+ export declare function cloudErrorOf(response: Response): Promise<ColyseusCloudApiError>;
201
+ /** Reads the Colyseus Cloud API with a team API token (read-only, GET only). */
202
+ export declare class ColyseusCloudClient {
203
+ /** Base URL without a trailing slash. */
204
+ private readonly baseUrl;
205
+ /** The team API token, sent as a Bearer token and never logged. */
206
+ private readonly apiToken;
207
+ /** Request timeout, in milliseconds. */
208
+ private readonly timeoutMs;
209
+ /**
210
+ * Creates a client.
211
+ * @param apiUrl The API base URL (config admin.colyseusCloud.apiUrl).
212
+ * @param apiToken The team API token.
213
+ * @param timeoutMs Request timeout in milliseconds.
214
+ */
215
+ constructor(apiUrl: string, apiToken: string, timeoutMs?: number);
216
+ /**
217
+ * GET /applications: the team's applications with their locations and instances.
218
+ * @returns The applications.
219
+ * @throws ColyseusCloudApiError on a failed or missing answer.
220
+ */
221
+ listApplications(): Promise<CloudApiApplication[]>;
222
+ /**
223
+ * GET /applications/{slug}/metrics/current: the latest sample of every location, instance and process.
224
+ * @param slug The application slug.
225
+ * @returns The current metrics.
226
+ * @throws ColyseusCloudApiError on a failed or missing answer.
227
+ */
228
+ currentMetrics(slug: string): Promise<CloudApiCurrentMetrics>;
229
+ /**
230
+ * GET /applications/{slug}/metrics: the load history of every location.
231
+ * @param slug The application slug.
232
+ * @param resolution "minute" (last 24 hours) or "day" (last 30 days).
233
+ * @returns The history.
234
+ * @throws ColyseusCloudApiError on a failed or missing answer.
235
+ */
236
+ metricsHistory(slug: string, resolution: CloudHistoryResolution): Promise<CloudApiHistory>;
237
+ /**
238
+ * GET /applications/{slug}/egress: the traffic of the last 30 days per location and day.
239
+ * @param slug The application slug.
240
+ * @returns The traffic.
241
+ * @throws ColyseusCloudApiError on a failed or missing answer.
242
+ */
243
+ egress(slug: string): Promise<CloudApiEgress>;
244
+ /**
245
+ * GET /applications/{slug}/deploys: the most recent deploys, newest first.
246
+ * @param slug The application slug.
247
+ * @param limit How many deploys to read.
248
+ * @returns The deploys.
249
+ * @throws ColyseusCloudApiError on a failed or missing answer.
250
+ */
251
+ deploys(slug: string, limit: number): Promise<CloudApiDeploy[]>;
252
+ /**
253
+ * GET /applications/{slug}/deploys/{deployId}: one deploy with its build and deploy output.
254
+ * @param slug The application slug.
255
+ * @param deployId Colyseus's deploy id.
256
+ * @returns The deploy with its output.
257
+ * @throws ColyseusCloudApiError on a failed or missing answer.
258
+ */
259
+ deploy(slug: string, deployId: number): Promise<CloudApiDeployDetail>;
260
+ /**
261
+ * GET /billing: the team owner's billing account and every application's subscription.
262
+ * @returns The billing figures.
263
+ * @throws ColyseusCloudApiError on a failed or missing answer.
264
+ */
265
+ billing(): Promise<CloudApiBilling>;
266
+ /**
267
+ * GET /applications/{slug}/instances/{instanceId}/logs: the newest log lines of one instance as plain text.
268
+ * @param slug The application slug.
269
+ * @param instanceId Colyseus's instance id.
270
+ * @param stream Which output stream to read.
271
+ * @param lines How many lines to read.
272
+ * @returns The log text.
273
+ * @throws ColyseusCloudApiError on a failed or missing answer.
274
+ */
275
+ instanceLogs(slug: string, instanceId: number, stream: CloudLogStream, lines: CloudLogLines): Promise<string>;
276
+ /**
277
+ * The path of one application, with its slug encoded.
278
+ * @param slug The application slug.
279
+ * @returns "/applications/{slug}".
280
+ */
281
+ private applicationPath;
282
+ /**
283
+ * Removes the token from a text before it becomes an error message: fetch rejects a token with an invalid header
284
+ * character (such as a newline from a multi-line .env value) with an error that quotes the whole Authorization value.
285
+ * @param text The text, e.g. fetch's error message.
286
+ * @returns The text with every occurrence of the token replaced by REDACTED_TOKEN.
287
+ */
288
+ private withoutToken;
289
+ /**
290
+ * GETs a JSON answer.
291
+ * @param path The path after the base URL.
292
+ * @param query Query parameters (empty object: none).
293
+ * @returns The parsed body.
294
+ * @throws ColyseusCloudApiError on a failed or missing answer.
295
+ */
296
+ private requestJson;
297
+ /**
298
+ * GETs a plain-text answer.
299
+ * @param path The path after the base URL.
300
+ * @param query Query parameters.
301
+ * @returns The text.
302
+ * @throws ColyseusCloudApiError on a failed or missing answer.
303
+ */
304
+ private requestText;
305
+ /**
306
+ * Sends one GET with the token and the timeout.
307
+ * @param path The path after the base URL.
308
+ * @param query Query parameters.
309
+ * @returns The successful answer.
310
+ * @throws ColyseusCloudApiError on a non-2xx answer or no answer.
311
+ */
312
+ private send;
313
+ }
@@ -0,0 +1,272 @@
1
+ // Read-only client of the Colyseus Cloud API behind the console's Colyseus Cloud page (colyseus-cloud-console D2, D5).
2
+ // It knows HTTP and Colyseus's raw shapes only; ColyseusCloudViews converts them and ColyseusCloudService times them.
3
+ import { COLYSEUS_CLOUD_DEFAULT_RETRY_SECONDS, COLYSEUS_CLOUD_MIN_RETRY_SECONDS, COLYSEUS_CLOUD_TIMEOUT_MS } from "./AdminConstants.js";
4
+ /** HTTP status of a rate-limited answer. */
5
+ const HTTP_TOO_MANY_REQUESTS = 429;
6
+ /** First HTTP status of a server error. */
7
+ const HTTP_SERVER_ERROR_START = 500;
8
+ /** HTTP statuses of a gateway that could not reach Colyseus. */
9
+ const GATEWAY_STATUSES = new Set([502, 503, 504]);
10
+ /** What replaces the token in an error message (fetch echoes an invalid Authorization value in its error, D2). */
11
+ const REDACTED_TOKEN = "[redacted]";
12
+ /** A Colyseus Cloud API failure: a non-2xx answer (plain-text proxy errors included) or no answer at all. */
13
+ export class ColyseusCloudApiError extends Error {
14
+ /** HTTP status, or 0 when Colyseus did not answer. */
15
+ status;
16
+ /** Colyseus's error code, or one derived from the status ("rate_limited", "unavailable", "server_error", "invalid_request", "unreachable"). */
17
+ code;
18
+ /** Seconds to wait before retrying (429, 5xx and no answer), or null when retrying sooner will not help. */
19
+ retryAfterSeconds;
20
+ /**
21
+ * Creates the error.
22
+ * @param status HTTP status, or 0 for no answer.
23
+ * @param code Stable error code.
24
+ * @param message Human-readable explanation (never contains the token).
25
+ * @param retryAfterSeconds Seconds to wait, or null.
26
+ */
27
+ constructor(status, code, message, retryAfterSeconds) {
28
+ super(message);
29
+ this.name = "ColyseusCloudApiError";
30
+ this.status = status;
31
+ this.code = code;
32
+ this.retryAfterSeconds = retryAfterSeconds;
33
+ }
34
+ /**
35
+ * The error as the console shows it.
36
+ * @returns The problem view.
37
+ */
38
+ toProblem() {
39
+ return { status: this.status, code: this.code, message: this.message };
40
+ }
41
+ }
42
+ /**
43
+ * Whether a parsed JSON value is Colyseus's error body.
44
+ * @param value The parsed body.
45
+ * @returns True for { error: { code: string, message: string } }.
46
+ */
47
+ function isCloudApiErrorBody(value) {
48
+ if (typeof value !== "object" || value == null)
49
+ return false;
50
+ const error = value.error;
51
+ if (typeof error !== "object" || error == null)
52
+ return false;
53
+ const fields = error;
54
+ return typeof fields.code === "string" && typeof fields.message === "string";
55
+ }
56
+ /**
57
+ * Seconds to wait after a failed answer (Colyseus's polling guide): Retry-After for 429 and 5xx, at least
58
+ * COLYSEUS_CLOUD_MIN_RETRY_SECONDS, COLYSEUS_CLOUD_DEFAULT_RETRY_SECONDS when missing or not a number; null otherwise.
59
+ * @param status The HTTP status.
60
+ * @param retryAfterHeader The Retry-After header, or null.
61
+ * @returns Seconds, or null.
62
+ */
63
+ export function retryAfterSecondsOf(status, retryAfterHeader) {
64
+ if (status !== HTTP_TOO_MANY_REQUESTS && status < HTTP_SERVER_ERROR_START)
65
+ return null;
66
+ const headerSeconds = Number(retryAfterHeader);
67
+ const seconds = (Number.isFinite(headerSeconds) && headerSeconds > 0) ? headerSeconds : COLYSEUS_CLOUD_DEFAULT_RETRY_SECONDS;
68
+ return Math.max(COLYSEUS_CLOUD_MIN_RETRY_SECONDS, seconds);
69
+ }
70
+ /**
71
+ * The error code of a failed answer that carries no Colyseus error body, derived from its status.
72
+ * @param status The HTTP status.
73
+ * @returns "rate_limited" for 429, "unavailable" for 502/503/504, "server_error" for another 5xx, else "invalid_request".
74
+ */
75
+ function errorCodeOfStatus(status) {
76
+ if (status === HTTP_TOO_MANY_REQUESTS)
77
+ return "rate_limited";
78
+ if (GATEWAY_STATUSES.has(status))
79
+ return "unavailable";
80
+ if (status >= HTTP_SERVER_ERROR_START)
81
+ return "server_error";
82
+ return "invalid_request";
83
+ }
84
+ /**
85
+ * Parses a body as JSON without throwing.
86
+ * @param text The body text.
87
+ * @returns The parsed value, or undefined when the text is not JSON (a plain-text proxy answer).
88
+ */
89
+ function parseJsonOrUndefined(text) {
90
+ try {
91
+ return JSON.parse(text);
92
+ }
93
+ catch {
94
+ return undefined;
95
+ }
96
+ }
97
+ /**
98
+ * The error of a non-2xx answer: Colyseus's JSON code and message when present, else the plain text with a code from
99
+ * the status (429 "rate_limited", 502/503/504 "unavailable", other 5xx "server_error", else "invalid_request").
100
+ * @param response The failed answer.
101
+ * @returns The error.
102
+ */
103
+ export async function cloudErrorOf(response) {
104
+ const status = response.status;
105
+ const retryAfterSeconds = retryAfterSecondsOf(status, response.headers.get("retry-after"));
106
+ const text = await response.text().catch(() => "");
107
+ const body = parseJsonOrUndefined(text);
108
+ if (isCloudApiErrorBody(body))
109
+ return new ColyseusCloudApiError(status, body.error.code, body.error.message, retryAfterSeconds);
110
+ const message = text.trim() || "Colyseus Cloud answered " + status;
111
+ return new ColyseusCloudApiError(status, errorCodeOfStatus(status), message, retryAfterSeconds);
112
+ }
113
+ /** Reads the Colyseus Cloud API with a team API token (read-only, GET only). */
114
+ export class ColyseusCloudClient {
115
+ /** Base URL without a trailing slash. */
116
+ baseUrl;
117
+ /** The team API token, sent as a Bearer token and never logged. */
118
+ apiToken;
119
+ /** Request timeout, in milliseconds. */
120
+ timeoutMs;
121
+ /**
122
+ * Creates a client.
123
+ * @param apiUrl The API base URL (config admin.colyseusCloud.apiUrl).
124
+ * @param apiToken The team API token.
125
+ * @param timeoutMs Request timeout in milliseconds.
126
+ */
127
+ constructor(apiUrl, apiToken, timeoutMs = COLYSEUS_CLOUD_TIMEOUT_MS) {
128
+ this.baseUrl = apiUrl.replace(/\/+$/, "");
129
+ this.apiToken = apiToken;
130
+ this.timeoutMs = timeoutMs;
131
+ }
132
+ /**
133
+ * GET /applications: the team's applications with their locations and instances.
134
+ * @returns The applications.
135
+ * @throws ColyseusCloudApiError on a failed or missing answer.
136
+ */
137
+ async listApplications() {
138
+ return (await this.requestJson("/applications", {})).data;
139
+ }
140
+ /**
141
+ * GET /applications/{slug}/metrics/current: the latest sample of every location, instance and process.
142
+ * @param slug The application slug.
143
+ * @returns The current metrics.
144
+ * @throws ColyseusCloudApiError on a failed or missing answer.
145
+ */
146
+ async currentMetrics(slug) {
147
+ return await this.requestJson(this.applicationPath(slug) + "/metrics/current", {});
148
+ }
149
+ /**
150
+ * GET /applications/{slug}/metrics: the load history of every location.
151
+ * @param slug The application slug.
152
+ * @param resolution "minute" (last 24 hours) or "day" (last 30 days).
153
+ * @returns The history.
154
+ * @throws ColyseusCloudApiError on a failed or missing answer.
155
+ */
156
+ async metricsHistory(slug, resolution) {
157
+ return await this.requestJson(this.applicationPath(slug) + "/metrics", { resolution: resolution });
158
+ }
159
+ /**
160
+ * GET /applications/{slug}/egress: the traffic of the last 30 days per location and day.
161
+ * @param slug The application slug.
162
+ * @returns The traffic.
163
+ * @throws ColyseusCloudApiError on a failed or missing answer.
164
+ */
165
+ async egress(slug) {
166
+ return await this.requestJson(this.applicationPath(slug) + "/egress", {});
167
+ }
168
+ /**
169
+ * GET /applications/{slug}/deploys: the most recent deploys, newest first.
170
+ * @param slug The application slug.
171
+ * @param limit How many deploys to read.
172
+ * @returns The deploys.
173
+ * @throws ColyseusCloudApiError on a failed or missing answer.
174
+ */
175
+ async deploys(slug, limit) {
176
+ return (await this.requestJson(this.applicationPath(slug) + "/deploys", { limit: String(limit) })).data;
177
+ }
178
+ /**
179
+ * GET /applications/{slug}/deploys/{deployId}: one deploy with its build and deploy output.
180
+ * @param slug The application slug.
181
+ * @param deployId Colyseus's deploy id.
182
+ * @returns The deploy with its output.
183
+ * @throws ColyseusCloudApiError on a failed or missing answer.
184
+ */
185
+ async deploy(slug, deployId) {
186
+ return (await this.requestJson(this.applicationPath(slug) + "/deploys/" + deployId, {})).data;
187
+ }
188
+ /**
189
+ * GET /billing: the team owner's billing account and every application's subscription.
190
+ * @returns The billing figures.
191
+ * @throws ColyseusCloudApiError on a failed or missing answer.
192
+ */
193
+ async billing() {
194
+ return await this.requestJson("/billing", {});
195
+ }
196
+ /**
197
+ * GET /applications/{slug}/instances/{instanceId}/logs: the newest log lines of one instance as plain text.
198
+ * @param slug The application slug.
199
+ * @param instanceId Colyseus's instance id.
200
+ * @param stream Which output stream to read.
201
+ * @param lines How many lines to read.
202
+ * @returns The log text.
203
+ * @throws ColyseusCloudApiError on a failed or missing answer.
204
+ */
205
+ async instanceLogs(slug, instanceId, stream, lines) {
206
+ const path = this.applicationPath(slug) + "/instances/" + instanceId + "/logs";
207
+ return await this.requestText(path, { stream: stream, lines: String(lines) });
208
+ }
209
+ /**
210
+ * The path of one application, with its slug encoded.
211
+ * @param slug The application slug.
212
+ * @returns "/applications/{slug}".
213
+ */
214
+ applicationPath(slug) {
215
+ return "/applications/" + encodeURIComponent(slug);
216
+ }
217
+ /**
218
+ * Removes the token from a text before it becomes an error message: fetch rejects a token with an invalid header
219
+ * character (such as a newline from a multi-line .env value) with an error that quotes the whole Authorization value.
220
+ * @param text The text, e.g. fetch's error message.
221
+ * @returns The text with every occurrence of the token replaced by REDACTED_TOKEN.
222
+ */
223
+ withoutToken(text) {
224
+ if (this.apiToken === "")
225
+ return text;
226
+ return text.replaceAll(this.apiToken, REDACTED_TOKEN);
227
+ }
228
+ /**
229
+ * GETs a JSON answer.
230
+ * @param path The path after the base URL.
231
+ * @param query Query parameters (empty object: none).
232
+ * @returns The parsed body.
233
+ * @throws ColyseusCloudApiError on a failed or missing answer.
234
+ */
235
+ async requestJson(path, query) {
236
+ const response = await this.send(path, query);
237
+ return await response.json();
238
+ }
239
+ /**
240
+ * GETs a plain-text answer.
241
+ * @param path The path after the base URL.
242
+ * @param query Query parameters.
243
+ * @returns The text.
244
+ * @throws ColyseusCloudApiError on a failed or missing answer.
245
+ */
246
+ async requestText(path, query) {
247
+ const response = await this.send(path, query);
248
+ return await response.text();
249
+ }
250
+ /**
251
+ * Sends one GET with the token and the timeout.
252
+ * @param path The path after the base URL.
253
+ * @param query Query parameters.
254
+ * @returns The successful answer.
255
+ * @throws ColyseusCloudApiError on a non-2xx answer or no answer.
256
+ */
257
+ async send(path, query) {
258
+ const queryText = new URLSearchParams(query).toString();
259
+ const url = this.baseUrl + path + (queryText === "" ? "" : "?" + queryText);
260
+ let response;
261
+ try {
262
+ response = await fetch(url, { method: "GET", headers: { authorization: "Bearer " + this.apiToken, accept: "application/json" }, signal: AbortSignal.timeout(this.timeoutMs) });
263
+ }
264
+ catch (error) {
265
+ const reason = this.withoutToken((error instanceof Error) ? error.message : String(error));
266
+ throw new ColyseusCloudApiError(0, "unreachable", "Colyseus Cloud did not answer: " + reason, COLYSEUS_CLOUD_DEFAULT_RETRY_SECONDS);
267
+ }
268
+ if (!response.ok)
269
+ throw await cloudErrorOf(response);
270
+ return response;
271
+ }
272
+ }
@@ -0,0 +1,8 @@
1
+ import { type AdminApiRouter } from "./AdminApiRouter.js";
2
+ import type { AdminServices } from "./AdminServices.js";
3
+ /**
4
+ * Registers the five Colyseus Cloud routes.
5
+ * @param router The admin API router.
6
+ * @param services The shared services.
7
+ */
8
+ export declare function registerColyseusCloudRoutes(router: AdminApiRouter, services: AdminServices): void;
@@ -0,0 +1,91 @@
1
+ // The Colyseus Cloud page's routes (colyseus-cloud-console D7, D9, D10): the summary, the load history, billing,
2
+ // deploy output and instance logs. Every route reads ColyseusCloudService; only deploy output and logs reach the Cloud
3
+ // API, on request. All are reads: no step-up, no audit entry, API keys allowed.
4
+ import { AdminRequestError } from "./AdminApiRouter.js";
5
+ /** HTTP status of a successful read. */
6
+ const HTTP_OK = 200;
7
+ /** HTTP status of an invalid id or query. */
8
+ const HTTP_BAD_REQUEST = 400;
9
+ /** HTTP status of a route parameter that is missing (the router always fills matched ones). */
10
+ const HTTP_NOT_FOUND = 404;
11
+ /** The number of log lines a request without `lines` reads. */
12
+ const DEFAULT_LOG_LINES = 100;
13
+ /** The numbers of log lines Colyseus serves. */
14
+ const LOG_LINE_CHOICES = [100, 500];
15
+ /** The log streams Colyseus serves. */
16
+ const LOG_STREAMS = ["all", "out", "err"];
17
+ /** The stream a log request without `stream` reads. */
18
+ const DEFAULT_LOG_STREAM = "all";
19
+ /** A positive whole number without leading zeros. */
20
+ const POSITIVE_ID_PATTERN = /^[1-9][0-9]*$/;
21
+ /**
22
+ * Registers the five Colyseus Cloud routes.
23
+ * @param router The admin API router.
24
+ * @param services The shared services.
25
+ */
26
+ export function registerColyseusCloudRoutes(router, services) {
27
+ const routes = [
28
+ { method: "GET", pattern: "cloud", permission: "cloud.view", requiresStepUp: false, auditAction: null, handler: async () => ({ status: HTTP_OK, body: await services.colyseusCloud.readSummary() }) },
29
+ { method: "GET", pattern: "cloud/history", permission: "cloud.view", requiresStepUp: false, auditAction: null, handler: async (request) => ({ status: HTTP_OK, body: await services.colyseusCloud.readHistory() }) },
30
+ { method: "GET", pattern: "cloud/billing", permission: "cloud.billing", requiresStepUp: false, auditAction: null, handler: async () => ({ status: HTTP_OK, body: await services.colyseusCloud.readBilling() }) },
31
+ { method: "GET", pattern: "cloud/deploys/:deployId", permission: "cloud.view", requiresStepUp: false, auditAction: null, handler: async (request) => ({ status: HTTP_OK, body: await services.colyseusCloud.readDeploy(positiveIdOf(request.params.deployId, "deployId")) }) },
32
+ { method: "GET", pattern: "cloud/instances/:instanceId/logs", permission: "logs.view", requiresStepUp: false, auditAction: null, handler: async (request) => ({ status: HTTP_OK, body: await readInstanceLogs(services, request) }) }
33
+ ];
34
+ for (const route of routes)
35
+ router.register(route);
36
+ }
37
+ /**
38
+ * GET cloud/instances/:instanceId/logs: validates the id, stream and lines, then reads the logs through the fleet gate.
39
+ * @param services The shared services.
40
+ * @param request The request (params instanceId; query stream, lines).
41
+ * @returns The logs view.
42
+ * @throws AdminRequestError 400 for an invalid id, stream or lines, or the service's refusals.
43
+ */
44
+ async function readInstanceLogs(services, request) {
45
+ const instanceId = positiveIdOf(request.params.instanceId, "instanceId");
46
+ const stream = streamOf(request.query.get("stream"));
47
+ const lines = linesOf(request.query.get("lines"));
48
+ return await services.colyseusCloud.readLogs(instanceId, stream, lines);
49
+ }
50
+ /**
51
+ * A positive whole-number id of a route parameter.
52
+ * @param text The parameter value.
53
+ * @param name The parameter name, for the error message.
54
+ * @returns The id.
55
+ * @throws AdminRequestError 400 when it is not a positive whole number (404 when the parameter is missing).
56
+ */
57
+ function positiveIdOf(text, name) {
58
+ if (text == null)
59
+ throw new AdminRequestError(HTTP_NOT_FOUND, name + " is missing");
60
+ if (!POSITIVE_ID_PATTERN.test(text))
61
+ throw new AdminRequestError(HTTP_BAD_REQUEST, name + " must be a positive whole number");
62
+ return Number(text);
63
+ }
64
+ /**
65
+ * The log stream of a query value.
66
+ * @param text The `stream` query value, or null.
67
+ * @returns "all" when empty, else the value.
68
+ * @throws AdminRequestError 400 for any other value.
69
+ */
70
+ function streamOf(text) {
71
+ if (text == null || text === "")
72
+ return DEFAULT_LOG_STREAM;
73
+ const stream = LOG_STREAMS.find((candidate) => candidate === text);
74
+ if (stream == null)
75
+ throw new AdminRequestError(HTTP_BAD_REQUEST, "stream must be all, out or err");
76
+ return stream;
77
+ }
78
+ /**
79
+ * The number of log lines of a query value.
80
+ * @param text The `lines` query value, or null.
81
+ * @returns DEFAULT_LOG_LINES when empty, else the value.
82
+ * @throws AdminRequestError 400 for any other value.
83
+ */
84
+ function linesOf(text) {
85
+ if (text == null || text === "")
86
+ return DEFAULT_LOG_LINES;
87
+ const lines = LOG_LINE_CHOICES.find((candidate) => String(candidate) === text);
88
+ if (lines == null)
89
+ throw new AdminRequestError(HTTP_BAD_REQUEST, "lines must be 100 or 500");
90
+ return lines;
91
+ }