import './Room.ext.ts'; import { Server, Room, matchMaker, type SDKTypes } from "@colyseus/core"; import { ColyseusSDK, type Room as SDKRoom, type InferRoomConstructor } from "@colyseus/sdk"; import * as httpie from "httpie"; export class ColyseusTestServer { public server: Server; public sdk: ColyseusSDK; // // TODO: deprecate this on Colyseus 1.0. // Use `sdk.http` instead (which uses the auth token automatically) // public http: { get: typeof httpie.get, post: typeof httpie.post, patch: typeof httpie.patch, delete: typeof httpie.del, put: typeof httpie.put, }; constructor(server: Server) { this.server = server; const hostname = "127.0.0.1"; const port = server['port']; this.sdk = new ColyseusSDK(`ws://${hostname}:${port}`); const httpEndpoint = `http://${hostname}:${port}`; this.http = { ['get']: (segments, opts) => httpie.get(`${httpEndpoint}${segments}`, opts), ['post']: (segments, opts) => httpie.post(`${httpEndpoint}${segments}`, opts), ['patch']: (segments, opts) => httpie.patch(`${httpEndpoint}${segments}`, opts), ['delete']: (segments, opts) => httpie.del(`${httpEndpoint}${segments}`, opts), ['put']: (segments, opts) => httpie.put(`${httpEndpoint}${segments}`, opts), }; } // Overload: Use room name from ServerType to infer room type async createRoom( roomName: R, clientOptions?: Parameters[1] ): Promise; // Overload: Pass Room type directly async createRoom( roomName: string, clientOptions?: any ): Promise; // Overload: Pass State and Metadata type directly async createRoom( // TODO: deprecate on v1.0 roomName: string, clientOptions?: any ): Promise>; // Implementation async createRoom(roomName: string, clientOptions: any = {}) { const room = await matchMaker.createRoom(roomName, clientOptions); return this.getRoomById(room.roomId); } async connectTo( room: RoomInstance, clientOptions: any = {}, ): Promise> { const client = await this.sdk.joinById(room.roomId, clientOptions); // otherwise `client.state` stays empty for a round-trip, and every // assertion on it races the room's patch interval await client.waitForInitialState(); return client; } // Overload: Pass Room type directly getRoomById(roomId: string): T; // Overload: Pass State and Metadata type directly getRoomById(roomId: string): Room<{ state: State, metadata: Metadata }>; // Implementation getRoomById(roomId: string) { return matchMaker.getLocalRoomById(roomId); } async cleanup() { // ensure no rooms are still alive await Promise.all(matchMaker.disconnectAll()); await this.sdk.auth.signOut(); const driver = this.server['driver']; if (driver) { await driver.clear(); } } async shutdown() { await this.server.gracefullyShutdown(false); } }