@colyseus/core 0.17.26 → 0.17.28
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/Server.cjs +2 -2
- package/build/Server.cjs.map +2 -2
- package/build/Server.d.ts +1 -1
- package/build/Server.mjs +3 -3
- package/build/Server.mjs.map +2 -2
- package/build/index.cjs +2 -2
- package/build/index.cjs.map +2 -2
- package/build/index.d.ts +1 -1
- package/build/index.mjs +2 -2
- package/build/index.mjs.map +2 -2
- package/build/utils/Utils.cjs +16 -5
- package/build/utils/Utils.cjs.map +2 -2
- package/build/utils/Utils.d.ts +8 -3
- package/build/utils/Utils.mjs +22 -4
- package/build/utils/Utils.mjs.map +2 -2
- package/package.json +4 -4
- package/src/Server.ts +3 -3
- package/src/index.ts +1 -1
- package/src/utils/Utils.ts +24 -3
package/build/Server.cjs
CHANGED
|
@@ -103,7 +103,7 @@ var Server = class {
|
|
|
103
103
|
hostname = void 0;
|
|
104
104
|
} else {
|
|
105
105
|
try {
|
|
106
|
-
return (await
|
|
106
|
+
return (await (0, import_Utils.dynamicImport)("@colyseus/tools")).listen(this);
|
|
107
107
|
} catch (error) {
|
|
108
108
|
const err = new Error("Please install @colyseus/tools to be able to host on Colyseus Cloud.");
|
|
109
109
|
err.cause = error;
|
|
@@ -205,7 +205,7 @@ var Server = class {
|
|
|
205
205
|
}
|
|
206
206
|
async getDefaultTransport(options) {
|
|
207
207
|
try {
|
|
208
|
-
const module2 = await
|
|
208
|
+
const module2 = await (0, import_Utils.dynamicImport)("@colyseus/ws-transport");
|
|
209
209
|
const WebSocketTransport = module2.WebSocketTransport;
|
|
210
210
|
return new WebSocketTransport(options);
|
|
211
211
|
} catch (error) {
|
package/build/Server.cjs.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/Server.ts"],
|
|
4
|
-
"sourcesContent": ["import { greet } from \"@colyseus/greeting-banner\";\nimport type express from 'express';\n\nimport { debugAndPrintError } from './Debug.ts';\nimport * as matchMaker from './MatchMaker.ts';\nimport { RegisteredHandler } from './matchmaker/RegisteredHandler.ts';\n\nimport { type OnCreateOptions, Room } from './Room.ts';\nimport { Deferred, registerGracefulShutdown, type Type } from './utils/Utils.ts';\n\nimport type { Presence } from \"./presence/Presence.ts\";\nimport { LocalPresence } from './presence/LocalPresence.ts';\nimport { LocalDriver } from './matchmaker/LocalDriver/LocalDriver.ts';\n\nimport { setTransport, Transport } from './Transport.ts';\nimport { logger, setLogger } from './Logger.ts';\nimport { setDevMode, isDevMode } from './utils/DevMode.ts';\nimport { type Router, bindRouterToTransport } from './router/index.ts';\nimport { type SDKTypes as SharedSDKTypes } from '@colyseus/shared-types';\nimport { getDefaultRouter } from './router/default_routes.ts';\n\nexport type ServerOptions = {\n publicAddress?: string,\n presence?: Presence,\n driver?: matchMaker.MatchMakerDriver,\n transport?: Transport,\n gracefullyShutdown?: boolean,\n logger?: any;\n\n /**\n * Optional callback to execute before the server listens.\n * This is useful for example to connect into a database or other services before the server listens.\n */\n beforeListen?: () => Promise<void> | void,\n\n /**\n * Optional callback to configure Express routes.\n * When provided, the transport layer will initialize an Express-compatible app\n * and pass it to this callback for custom route configuration.\n *\n * For uWebSockets transport, this uses the uwebsockets-express module.\n */\n express?: (app: express.Application) => void,\n\n /**\n * Custom function to determine which process should handle room creation.\n * Default: assign new rooms the process with least amount of rooms created\n */\n selectProcessIdToCreateRoom?: matchMaker.SelectProcessIdCallback;\n\n /**\n * If enabled, rooms are going to be restored in the server-side upon restart,\n * clients are going to automatically re-connect when server reboots.\n *\n * Beware of \"schema mismatch\" issues. When updating Schema structures and\n * reloading existing data, you may see \"schema mismatch\" errors in the\n * client-side.\n *\n * (This operation is costly and should not be used in a production\n * environment)\n */\n devMode?: boolean,\n\n /**\n * Display greeting message on server start.\n * Default: true\n */\n greet?: boolean,\n};\n\n/**\n * Exposed types for the client-side SDK.\n * Re-exported from @colyseus/shared-types with specific type constraints.\n */\nexport interface SDKTypes<\n RoomTypes extends Record<string, RegisteredHandler> = any,\n Routes extends Router = any\n> extends SharedSDKTypes<RoomTypes, Routes> {}\n\nexport class Server<\n RoomTypes extends Record<string, RegisteredHandler> = any,\n Routes extends Router = any\n> implements SDKTypes<RoomTypes, Routes> {\n '~rooms': RoomTypes;\n '~routes': Routes;\n\n public transport: Transport;\n public router: Routes;\n public options: ServerOptions;\n\n protected presence: Presence;\n protected driver: matchMaker.MatchMakerDriver;\n\n protected port: number | string;\n protected greet: boolean;\n\n protected _onTransportReady = new Deferred<Transport>();\n\n private _originalRoomOnMessage: typeof Room.prototype['_onMessage'] | null = null;\n\n constructor(options: ServerOptions = {}) {\n const {\n gracefullyShutdown = true,\n greet = true\n } = options;\n\n setDevMode(options.devMode === true);\n\n this.presence = options.presence || new LocalPresence();\n this.driver = options.driver || new LocalDriver();\n this.options = options;\n this.greet = greet;\n\n this.attach(options);\n\n matchMaker.setup(\n this.presence,\n this.driver,\n options.publicAddress,\n options.selectProcessIdToCreateRoom,\n );\n\n if (gracefullyShutdown) {\n registerGracefulShutdown((err) => this.gracefullyShutdown(true, err));\n }\n\n if (options.logger) {\n setLogger(options.logger);\n }\n }\n\n public async attach(options: ServerOptions) {\n this.transport = options.transport || await this.getDefaultTransport(options);\n\n // Initialize Express if callback is provided\n if (options.express && this.transport.getExpressApp) {\n const expressApp = await this.transport.getExpressApp();\n options.express(expressApp);\n }\n\n // Resolve the promise when the transport is ready\n this._onTransportReady.resolve(this.transport);\n }\n\n /**\n * Bind the server into the port specified.\n *\n * @param port - Port number or Unix socket path\n * @param hostname\n * @param backlog\n * @param listeningListener\n */\n public async listen(port: number | string, hostname?: string, backlog?: number, listeningListener?: Function) {\n if (this.options.beforeListen) {\n await this.options.beforeListen();\n }\n\n //\n // if Colyseus Cloud is detected, use @colyseus/tools to listen\n //\n if (process.env.COLYSEUS_CLOUD !== undefined ) {\n if (typeof(hostname) === \"number\") {\n //\n // workaround, @colyseus/tools calls server.listen() again with the port as a string\n //\n hostname = undefined;\n\n } else {\n try {\n return (await import(\"@colyseus/tools\")).listen(this);\n } catch (error) {\n const err = new Error(\"Please install @colyseus/tools to be able to host on Colyseus Cloud.\");\n err.cause = error;\n throw err;\n }\n }\n }\n\n //\n // otherwise, listen on the port directly\n //\n this.port = port;\n\n //\n // Make sure matchmaker is ready before accepting connections\n // (isDevMode: matchmaker may take extra milliseconds to restore the rooms)\n //\n await matchMaker.accept();\n\n /**\n * Greetings!\n */\n if (this.greet) {\n greet();\n }\n\n // Wait for the transport to be ready\n await this._onTransportReady;\n\n return new Promise<void>((resolve, reject) => {\n // TODO: refactor me!\n // set transport globally, to be used by matchmaking route\n setTransport(this.transport);\n\n this.transport.listen(port, hostname, backlog, (err) => {\n if (this.transport.server) {\n this.transport.server.on('error', (err) => reject(err));\n }\n\n // default router is used if no router is provided\n if (!this.router) {\n this.router = getDefaultRouter() as unknown as Routes;\n\n } else {\n // make sure default routes are included\n // https://github.com/Bekacru/better-call/pull/67\n this.router = this.router.extend({ ...getDefaultRouter().endpoints }) as unknown as Routes;\n }\n\n bindRouterToTransport(this.transport, this.router);\n\n if (listeningListener) {\n listeningListener(err);\n }\n\n if (err) {\n reject(err);\n\n } else {\n resolve();\n }\n });\n });\n }\n\n /**\n * Define a new type of room for matchmaking.\n *\n * @param name public room identifier for match-making.\n * @param roomClass Room class definition\n * @param defaultOptions default options for `onCreate`\n */\n public define<T extends Type<Room>>(\n roomClass: T,\n defaultOptions?: OnCreateOptions<T>,\n ): RegisteredHandler\n public define<T extends Type<Room>>(\n name: string,\n roomClass: T,\n defaultOptions?: OnCreateOptions<T>,\n ): RegisteredHandler\n public define<T extends Type<Room>>(\n nameOrHandler: string | T,\n handlerOrOptions: T | OnCreateOptions<T>,\n defaultOptions?: OnCreateOptions<T>,\n ): RegisteredHandler {\n const name = (typeof(nameOrHandler) === \"string\")\n ? nameOrHandler\n : nameOrHandler.name;\n\n const roomClass = (typeof(nameOrHandler) === \"string\")\n ? handlerOrOptions\n : nameOrHandler;\n\n const options = (typeof(nameOrHandler) === \"string\")\n ? defaultOptions\n : handlerOrOptions;\n\n return matchMaker.defineRoomType(name, roomClass, options);\n }\n\n /**\n * Remove a room definition from matchmaking.\n * This method does not destroy any room. It only dissallows matchmaking\n */\n public removeRoomType(name: string): void {\n matchMaker.removeRoomType(name);\n }\n\n public async gracefullyShutdown(exit: boolean = true, err?: Error) {\n if (matchMaker.state === matchMaker.MatchMakerState.SHUTTING_DOWN) {\n return;\n }\n\n try {\n // custom \"before shutdown\" method\n await this.onBeforeShutdownCallback();\n\n // this is going to lock all rooms and wait for them to be disposed\n await matchMaker.gracefullyShutdown();\n\n this.transport.shutdown();\n this.presence.shutdown();\n await this.driver.shutdown();\n\n // custom \"after shutdown\" method\n await this.onShutdownCallback();\n\n } catch (e) {\n debugAndPrintError(`error during shutdown: ${e}`);\n\n } finally {\n if (exit) {\n process.exit((err && !isDevMode) ? 1 : 0);\n }\n }\n }\n\n /**\n * Add simulated latency between client and server.\n * @param milliseconds round trip latency in milliseconds.\n */\n public simulateLatency(milliseconds: number) {\n if (milliseconds > 0) {\n logger.warn(`\uD83D\uDCF6\uFE0F\u2757 Colyseus latency simulation enabled \u2192 ${milliseconds}ms latency for round trip.`);\n } else {\n logger.warn(`\uD83D\uDCF6\uFE0F\u2757 Colyseus latency simulation disabled.`);\n }\n\n const halfwayMS = (milliseconds / 2);\n this.transport.simulateLatency(halfwayMS);\n\n if (this._originalRoomOnMessage == null) {\n this._originalRoomOnMessage = Room.prototype['_onMessage'];\n }\n\n const originalOnMessage = this._originalRoomOnMessage;\n\n Room.prototype['_onMessage'] = milliseconds <= Number.EPSILON ? originalOnMessage : function (this: Room, client, buffer) {\n // uWebSockets.js: duplicate buffer because it is cleared at native layer before the timeout.\n const cachedBuffer = Buffer.from(buffer);\n setTimeout(() => originalOnMessage.call(this, client, cachedBuffer), halfwayMS);\n };\n }\n\n /**\n * Register a callback that is going to be executed before the server shuts down.\n * @param callback\n */\n public onShutdown(callback: () => void | Promise<any>) {\n this.onShutdownCallback = callback;\n }\n\n public onBeforeShutdown(callback: () => void | Promise<any>) {\n this.onBeforeShutdownCallback = callback;\n }\n\n protected async getDefaultTransport(options: any): Promise<Transport> {\n try {\n const module = await import('@colyseus/ws-transport');\n const WebSocketTransport = module.WebSocketTransport;\n return new WebSocketTransport(options);\n\n } catch (error) {\n this._onTransportReady.reject(error);\n throw new Error(\"Please provide a 'transport' layer. Default transport not set.\");\n }\n }\n\n protected onShutdownCallback: () => void | Promise<any> =\n () => Promise.resolve()\n\n protected onBeforeShutdownCallback: () => void | Promise<any> =\n () => Promise.resolve()\n}\n\nexport type DefineServerOptions<\n T extends Record<string, RegisteredHandler>,\n R extends Router\n> = ServerOptions & {\n rooms: T,\n routes?: R,\n};\n\nexport function defineServer<\n T extends Record<string, RegisteredHandler>,\n R extends Router\n>(\n options: DefineServerOptions<T, R>,\n): Server<T, R> {\n const { rooms, routes, ...serverOptions } = options;\n const server = new Server<T, R>(serverOptions);\n\n server.router = routes;\n\n for (const [name, handler] of Object.entries(rooms)) {\n handler.name = name;\n matchMaker.addRoomType(handler);\n }\n\n return server;\n}\n\nexport function defineRoom<T extends Type<Room>>(\n roomKlass: T,\n defaultOptions?: Parameters<NonNullable<InstanceType<T>['onCreate']>>[0],\n): RegisteredHandler<InstanceType<T>> {\n return new RegisteredHandler(roomKlass, defaultOptions) as unknown as RegisteredHandler<InstanceType<T>>;\n}"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,6BAAsB;AAGtB,mBAAmC;AACnC,iBAA4B;AAC5B,+BAAkC;AAElC,kBAA2C;AAC3C,
|
|
4
|
+
"sourcesContent": ["import { greet } from \"@colyseus/greeting-banner\";\nimport type express from 'express';\n\nimport { debugAndPrintError } from './Debug.ts';\nimport * as matchMaker from './MatchMaker.ts';\nimport { RegisteredHandler } from './matchmaker/RegisteredHandler.ts';\n\nimport { type OnCreateOptions, Room } from './Room.ts';\nimport { Deferred, registerGracefulShutdown, dynamicImport, type Type } from './utils/Utils.ts';\n\nimport type { Presence } from \"./presence/Presence.ts\";\nimport { LocalPresence } from './presence/LocalPresence.ts';\nimport { LocalDriver } from './matchmaker/LocalDriver/LocalDriver.ts';\n\nimport { setTransport, Transport } from './Transport.ts';\nimport { logger, setLogger } from './Logger.ts';\nimport { setDevMode, isDevMode } from './utils/DevMode.ts';\nimport { type Router, bindRouterToTransport } from './router/index.ts';\nimport { type SDKTypes as SharedSDKTypes } from '@colyseus/shared-types';\nimport { getDefaultRouter } from './router/default_routes.ts';\n\nexport type ServerOptions = {\n publicAddress?: string,\n presence?: Presence,\n driver?: matchMaker.MatchMakerDriver,\n transport?: Transport,\n gracefullyShutdown?: boolean,\n logger?: any;\n\n /**\n * Optional callback to execute before the server listens.\n * This is useful for example to connect into a database or other services before the server listens.\n */\n beforeListen?: () => Promise<void> | void,\n\n /**\n * Optional callback to configure Express routes.\n * When provided, the transport layer will initialize an Express-compatible app\n * and pass it to this callback for custom route configuration.\n *\n * For uWebSockets transport, this uses the uwebsockets-express module.\n */\n express?: (app: express.Application) => void,\n\n /**\n * Custom function to determine which process should handle room creation.\n * Default: assign new rooms the process with least amount of rooms created\n */\n selectProcessIdToCreateRoom?: matchMaker.SelectProcessIdCallback;\n\n /**\n * If enabled, rooms are going to be restored in the server-side upon restart,\n * clients are going to automatically re-connect when server reboots.\n *\n * Beware of \"schema mismatch\" issues. When updating Schema structures and\n * reloading existing data, you may see \"schema mismatch\" errors in the\n * client-side.\n *\n * (This operation is costly and should not be used in a production\n * environment)\n */\n devMode?: boolean,\n\n /**\n * Display greeting message on server start.\n * Default: true\n */\n greet?: boolean,\n};\n\n/**\n * Exposed types for the client-side SDK.\n * Re-exported from @colyseus/shared-types with specific type constraints.\n */\nexport interface SDKTypes<\n RoomTypes extends Record<string, RegisteredHandler> = any,\n Routes extends Router = any\n> extends SharedSDKTypes<RoomTypes, Routes> {}\n\nexport class Server<\n RoomTypes extends Record<string, RegisteredHandler> = any,\n Routes extends Router = any\n> implements SDKTypes<RoomTypes, Routes> {\n '~rooms': RoomTypes;\n '~routes': Routes;\n\n public transport: Transport;\n public router: Routes;\n public options: ServerOptions;\n\n protected presence: Presence;\n protected driver: matchMaker.MatchMakerDriver;\n\n protected port: number | string;\n protected greet: boolean;\n\n protected _onTransportReady = new Deferred<Transport>();\n\n private _originalRoomOnMessage: typeof Room.prototype['_onMessage'] | null = null;\n\n constructor(options: ServerOptions = {}) {\n const {\n gracefullyShutdown = true,\n greet = true\n } = options;\n\n setDevMode(options.devMode === true);\n\n this.presence = options.presence || new LocalPresence();\n this.driver = options.driver || new LocalDriver();\n this.options = options;\n this.greet = greet;\n\n this.attach(options);\n\n matchMaker.setup(\n this.presence,\n this.driver,\n options.publicAddress,\n options.selectProcessIdToCreateRoom,\n );\n\n if (gracefullyShutdown) {\n registerGracefulShutdown((err) => this.gracefullyShutdown(true, err));\n }\n\n if (options.logger) {\n setLogger(options.logger);\n }\n }\n\n public async attach(options: ServerOptions) {\n this.transport = options.transport || await this.getDefaultTransport(options);\n\n // Initialize Express if callback is provided\n if (options.express && this.transport.getExpressApp) {\n const expressApp = await this.transport.getExpressApp();\n options.express(expressApp);\n }\n\n // Resolve the promise when the transport is ready\n this._onTransportReady.resolve(this.transport);\n }\n\n /**\n * Bind the server into the port specified.\n *\n * @param port - Port number or Unix socket path\n * @param hostname\n * @param backlog\n * @param listeningListener\n */\n public async listen(port: number | string, hostname?: string, backlog?: number, listeningListener?: Function) {\n if (this.options.beforeListen) {\n await this.options.beforeListen();\n }\n\n //\n // if Colyseus Cloud is detected, use @colyseus/tools to listen\n //\n if (process.env.COLYSEUS_CLOUD !== undefined ) {\n if (typeof(hostname) === \"number\") {\n //\n // workaround, @colyseus/tools calls server.listen() again with the port as a string\n //\n hostname = undefined;\n\n } else {\n try {\n return (await dynamicImport(\"@colyseus/tools\")).listen(this);\n } catch (error) {\n const err = new Error(\"Please install @colyseus/tools to be able to host on Colyseus Cloud.\");\n err.cause = error;\n throw err;\n }\n }\n }\n\n //\n // otherwise, listen on the port directly\n //\n this.port = port;\n\n //\n // Make sure matchmaker is ready before accepting connections\n // (isDevMode: matchmaker may take extra milliseconds to restore the rooms)\n //\n await matchMaker.accept();\n\n /**\n * Greetings!\n */\n if (this.greet) {\n greet();\n }\n\n // Wait for the transport to be ready\n await this._onTransportReady;\n\n return new Promise<void>((resolve, reject) => {\n // TODO: refactor me!\n // set transport globally, to be used by matchmaking route\n setTransport(this.transport);\n\n this.transport.listen(port, hostname, backlog, (err) => {\n if (this.transport.server) {\n this.transport.server.on('error', (err) => reject(err));\n }\n\n // default router is used if no router is provided\n if (!this.router) {\n this.router = getDefaultRouter() as unknown as Routes;\n\n } else {\n // make sure default routes are included\n // https://github.com/Bekacru/better-call/pull/67\n this.router = this.router.extend({ ...getDefaultRouter().endpoints }) as unknown as Routes;\n }\n\n bindRouterToTransport(this.transport, this.router);\n\n if (listeningListener) {\n listeningListener(err);\n }\n\n if (err) {\n reject(err);\n\n } else {\n resolve();\n }\n });\n });\n }\n\n /**\n * Define a new type of room for matchmaking.\n *\n * @param name public room identifier for match-making.\n * @param roomClass Room class definition\n * @param defaultOptions default options for `onCreate`\n */\n public define<T extends Type<Room>>(\n roomClass: T,\n defaultOptions?: OnCreateOptions<T>,\n ): RegisteredHandler\n public define<T extends Type<Room>>(\n name: string,\n roomClass: T,\n defaultOptions?: OnCreateOptions<T>,\n ): RegisteredHandler\n public define<T extends Type<Room>>(\n nameOrHandler: string | T,\n handlerOrOptions: T | OnCreateOptions<T>,\n defaultOptions?: OnCreateOptions<T>,\n ): RegisteredHandler {\n const name = (typeof(nameOrHandler) === \"string\")\n ? nameOrHandler\n : nameOrHandler.name;\n\n const roomClass = (typeof(nameOrHandler) === \"string\")\n ? handlerOrOptions\n : nameOrHandler;\n\n const options = (typeof(nameOrHandler) === \"string\")\n ? defaultOptions\n : handlerOrOptions;\n\n return matchMaker.defineRoomType(name, roomClass, options);\n }\n\n /**\n * Remove a room definition from matchmaking.\n * This method does not destroy any room. It only dissallows matchmaking\n */\n public removeRoomType(name: string): void {\n matchMaker.removeRoomType(name);\n }\n\n public async gracefullyShutdown(exit: boolean = true, err?: Error) {\n if (matchMaker.state === matchMaker.MatchMakerState.SHUTTING_DOWN) {\n return;\n }\n\n try {\n // custom \"before shutdown\" method\n await this.onBeforeShutdownCallback();\n\n // this is going to lock all rooms and wait for them to be disposed\n await matchMaker.gracefullyShutdown();\n\n this.transport.shutdown();\n this.presence.shutdown();\n await this.driver.shutdown();\n\n // custom \"after shutdown\" method\n await this.onShutdownCallback();\n\n } catch (e) {\n debugAndPrintError(`error during shutdown: ${e}`);\n\n } finally {\n if (exit) {\n process.exit((err && !isDevMode) ? 1 : 0);\n }\n }\n }\n\n /**\n * Add simulated latency between client and server.\n * @param milliseconds round trip latency in milliseconds.\n */\n public simulateLatency(milliseconds: number) {\n if (milliseconds > 0) {\n logger.warn(`\uD83D\uDCF6\uFE0F\u2757 Colyseus latency simulation enabled \u2192 ${milliseconds}ms latency for round trip.`);\n } else {\n logger.warn(`\uD83D\uDCF6\uFE0F\u2757 Colyseus latency simulation disabled.`);\n }\n\n const halfwayMS = (milliseconds / 2);\n this.transport.simulateLatency(halfwayMS);\n\n if (this._originalRoomOnMessage == null) {\n this._originalRoomOnMessage = Room.prototype['_onMessage'];\n }\n\n const originalOnMessage = this._originalRoomOnMessage;\n\n Room.prototype['_onMessage'] = milliseconds <= Number.EPSILON ? originalOnMessage : function (this: Room, client, buffer) {\n // uWebSockets.js: duplicate buffer because it is cleared at native layer before the timeout.\n const cachedBuffer = Buffer.from(buffer);\n setTimeout(() => originalOnMessage.call(this, client, cachedBuffer), halfwayMS);\n };\n }\n\n /**\n * Register a callback that is going to be executed before the server shuts down.\n * @param callback\n */\n public onShutdown(callback: () => void | Promise<any>) {\n this.onShutdownCallback = callback;\n }\n\n public onBeforeShutdown(callback: () => void | Promise<any>) {\n this.onBeforeShutdownCallback = callback;\n }\n\n protected async getDefaultTransport(options: any): Promise<Transport> {\n try {\n const module = await dynamicImport('@colyseus/ws-transport');\n const WebSocketTransport = module.WebSocketTransport;\n return new WebSocketTransport(options);\n\n } catch (error) {\n this._onTransportReady.reject(error);\n throw new Error(\"Please provide a 'transport' layer. Default transport not set.\");\n }\n }\n\n protected onShutdownCallback: () => void | Promise<any> =\n () => Promise.resolve()\n\n protected onBeforeShutdownCallback: () => void | Promise<any> =\n () => Promise.resolve()\n}\n\nexport type DefineServerOptions<\n T extends Record<string, RegisteredHandler>,\n R extends Router\n> = ServerOptions & {\n rooms: T,\n routes?: R,\n};\n\nexport function defineServer<\n T extends Record<string, RegisteredHandler>,\n R extends Router\n>(\n options: DefineServerOptions<T, R>,\n): Server<T, R> {\n const { rooms, routes, ...serverOptions } = options;\n const server = new Server<T, R>(serverOptions);\n\n server.router = routes;\n\n for (const [name, handler] of Object.entries(rooms)) {\n handler.name = name;\n matchMaker.addRoomType(handler);\n }\n\n return server;\n}\n\nexport function defineRoom<T extends Type<Room>>(\n roomKlass: T,\n defaultOptions?: Parameters<NonNullable<InstanceType<T>['onCreate']>>[0],\n): RegisteredHandler<InstanceType<T>> {\n return new RegisteredHandler(roomKlass, defaultOptions) as unknown as RegisteredHandler<InstanceType<T>>;\n}"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["gracefullyShutdown", "greet", "err", "module"]
|
|
7
7
|
}
|
package/build/Server.d.ts
CHANGED
|
@@ -78,7 +78,7 @@ export declare class Server<RoomTypes extends Record<string, RegisteredHandler>
|
|
|
78
78
|
* @param backlog
|
|
79
79
|
* @param listeningListener
|
|
80
80
|
*/
|
|
81
|
-
listen(port: number | string, hostname?: string, backlog?: number, listeningListener?: Function): Promise<
|
|
81
|
+
listen(port: number | string, hostname?: string, backlog?: number, listeningListener?: Function): Promise<any>;
|
|
82
82
|
/**
|
|
83
83
|
* Define a new type of room for matchmaking.
|
|
84
84
|
*
|
package/build/Server.mjs
CHANGED
|
@@ -4,7 +4,7 @@ import { debugAndPrintError } from "./Debug.mjs";
|
|
|
4
4
|
import * as matchMaker from "./MatchMaker.mjs";
|
|
5
5
|
import { RegisteredHandler } from "./matchmaker/RegisteredHandler.mjs";
|
|
6
6
|
import { Room } from "./Room.mjs";
|
|
7
|
-
import { Deferred, registerGracefulShutdown } from "./utils/Utils.mjs";
|
|
7
|
+
import { Deferred, registerGracefulShutdown, dynamicImport } from "./utils/Utils.mjs";
|
|
8
8
|
import { LocalPresence } from "./presence/LocalPresence.mjs";
|
|
9
9
|
import { LocalDriver } from "./matchmaker/LocalDriver/LocalDriver.mjs";
|
|
10
10
|
import { setTransport } from "./Transport.mjs";
|
|
@@ -67,7 +67,7 @@ var Server = class {
|
|
|
67
67
|
hostname = void 0;
|
|
68
68
|
} else {
|
|
69
69
|
try {
|
|
70
|
-
return (await
|
|
70
|
+
return (await dynamicImport("@colyseus/tools")).listen(this);
|
|
71
71
|
} catch (error) {
|
|
72
72
|
const err = new Error("Please install @colyseus/tools to be able to host on Colyseus Cloud.");
|
|
73
73
|
err.cause = error;
|
|
@@ -169,7 +169,7 @@ var Server = class {
|
|
|
169
169
|
}
|
|
170
170
|
async getDefaultTransport(options) {
|
|
171
171
|
try {
|
|
172
|
-
const module = await
|
|
172
|
+
const module = await dynamicImport("@colyseus/ws-transport");
|
|
173
173
|
const WebSocketTransport = module.WebSocketTransport;
|
|
174
174
|
return new WebSocketTransport(options);
|
|
175
175
|
} catch (error) {
|
package/build/Server.mjs.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/Server.ts"],
|
|
4
|
-
"sourcesContent": ["import { greet } from \"@colyseus/greeting-banner\";\nimport type express from 'express';\n\nimport { debugAndPrintError } from './Debug.ts';\nimport * as matchMaker from './MatchMaker.ts';\nimport { RegisteredHandler } from './matchmaker/RegisteredHandler.ts';\n\nimport { type OnCreateOptions, Room } from './Room.ts';\nimport { Deferred, registerGracefulShutdown, type Type } from './utils/Utils.ts';\n\nimport type { Presence } from \"./presence/Presence.ts\";\nimport { LocalPresence } from './presence/LocalPresence.ts';\nimport { LocalDriver } from './matchmaker/LocalDriver/LocalDriver.ts';\n\nimport { setTransport, Transport } from './Transport.ts';\nimport { logger, setLogger } from './Logger.ts';\nimport { setDevMode, isDevMode } from './utils/DevMode.ts';\nimport { type Router, bindRouterToTransport } from './router/index.ts';\nimport { type SDKTypes as SharedSDKTypes } from '@colyseus/shared-types';\nimport { getDefaultRouter } from './router/default_routes.ts';\n\nexport type ServerOptions = {\n publicAddress?: string,\n presence?: Presence,\n driver?: matchMaker.MatchMakerDriver,\n transport?: Transport,\n gracefullyShutdown?: boolean,\n logger?: any;\n\n /**\n * Optional callback to execute before the server listens.\n * This is useful for example to connect into a database or other services before the server listens.\n */\n beforeListen?: () => Promise<void> | void,\n\n /**\n * Optional callback to configure Express routes.\n * When provided, the transport layer will initialize an Express-compatible app\n * and pass it to this callback for custom route configuration.\n *\n * For uWebSockets transport, this uses the uwebsockets-express module.\n */\n express?: (app: express.Application) => void,\n\n /**\n * Custom function to determine which process should handle room creation.\n * Default: assign new rooms the process with least amount of rooms created\n */\n selectProcessIdToCreateRoom?: matchMaker.SelectProcessIdCallback;\n\n /**\n * If enabled, rooms are going to be restored in the server-side upon restart,\n * clients are going to automatically re-connect when server reboots.\n *\n * Beware of \"schema mismatch\" issues. When updating Schema structures and\n * reloading existing data, you may see \"schema mismatch\" errors in the\n * client-side.\n *\n * (This operation is costly and should not be used in a production\n * environment)\n */\n devMode?: boolean,\n\n /**\n * Display greeting message on server start.\n * Default: true\n */\n greet?: boolean,\n};\n\n/**\n * Exposed types for the client-side SDK.\n * Re-exported from @colyseus/shared-types with specific type constraints.\n */\nexport interface SDKTypes<\n RoomTypes extends Record<string, RegisteredHandler> = any,\n Routes extends Router = any\n> extends SharedSDKTypes<RoomTypes, Routes> {}\n\nexport class Server<\n RoomTypes extends Record<string, RegisteredHandler> = any,\n Routes extends Router = any\n> implements SDKTypes<RoomTypes, Routes> {\n '~rooms': RoomTypes;\n '~routes': Routes;\n\n public transport: Transport;\n public router: Routes;\n public options: ServerOptions;\n\n protected presence: Presence;\n protected driver: matchMaker.MatchMakerDriver;\n\n protected port: number | string;\n protected greet: boolean;\n\n protected _onTransportReady = new Deferred<Transport>();\n\n private _originalRoomOnMessage: typeof Room.prototype['_onMessage'] | null = null;\n\n constructor(options: ServerOptions = {}) {\n const {\n gracefullyShutdown = true,\n greet = true\n } = options;\n\n setDevMode(options.devMode === true);\n\n this.presence = options.presence || new LocalPresence();\n this.driver = options.driver || new LocalDriver();\n this.options = options;\n this.greet = greet;\n\n this.attach(options);\n\n matchMaker.setup(\n this.presence,\n this.driver,\n options.publicAddress,\n options.selectProcessIdToCreateRoom,\n );\n\n if (gracefullyShutdown) {\n registerGracefulShutdown((err) => this.gracefullyShutdown(true, err));\n }\n\n if (options.logger) {\n setLogger(options.logger);\n }\n }\n\n public async attach(options: ServerOptions) {\n this.transport = options.transport || await this.getDefaultTransport(options);\n\n // Initialize Express if callback is provided\n if (options.express && this.transport.getExpressApp) {\n const expressApp = await this.transport.getExpressApp();\n options.express(expressApp);\n }\n\n // Resolve the promise when the transport is ready\n this._onTransportReady.resolve(this.transport);\n }\n\n /**\n * Bind the server into the port specified.\n *\n * @param port - Port number or Unix socket path\n * @param hostname\n * @param backlog\n * @param listeningListener\n */\n public async listen(port: number | string, hostname?: string, backlog?: number, listeningListener?: Function) {\n if (this.options.beforeListen) {\n await this.options.beforeListen();\n }\n\n //\n // if Colyseus Cloud is detected, use @colyseus/tools to listen\n //\n if (process.env.COLYSEUS_CLOUD !== undefined ) {\n if (typeof(hostname) === \"number\") {\n //\n // workaround, @colyseus/tools calls server.listen() again with the port as a string\n //\n hostname = undefined;\n\n } else {\n try {\n return (await import(\"@colyseus/tools\")).listen(this);\n } catch (error) {\n const err = new Error(\"Please install @colyseus/tools to be able to host on Colyseus Cloud.\");\n err.cause = error;\n throw err;\n }\n }\n }\n\n //\n // otherwise, listen on the port directly\n //\n this.port = port;\n\n //\n // Make sure matchmaker is ready before accepting connections\n // (isDevMode: matchmaker may take extra milliseconds to restore the rooms)\n //\n await matchMaker.accept();\n\n /**\n * Greetings!\n */\n if (this.greet) {\n greet();\n }\n\n // Wait for the transport to be ready\n await this._onTransportReady;\n\n return new Promise<void>((resolve, reject) => {\n // TODO: refactor me!\n // set transport globally, to be used by matchmaking route\n setTransport(this.transport);\n\n this.transport.listen(port, hostname, backlog, (err) => {\n if (this.transport.server) {\n this.transport.server.on('error', (err) => reject(err));\n }\n\n // default router is used if no router is provided\n if (!this.router) {\n this.router = getDefaultRouter() as unknown as Routes;\n\n } else {\n // make sure default routes are included\n // https://github.com/Bekacru/better-call/pull/67\n this.router = this.router.extend({ ...getDefaultRouter().endpoints }) as unknown as Routes;\n }\n\n bindRouterToTransport(this.transport, this.router);\n\n if (listeningListener) {\n listeningListener(err);\n }\n\n if (err) {\n reject(err);\n\n } else {\n resolve();\n }\n });\n });\n }\n\n /**\n * Define a new type of room for matchmaking.\n *\n * @param name public room identifier for match-making.\n * @param roomClass Room class definition\n * @param defaultOptions default options for `onCreate`\n */\n public define<T extends Type<Room>>(\n roomClass: T,\n defaultOptions?: OnCreateOptions<T>,\n ): RegisteredHandler\n public define<T extends Type<Room>>(\n name: string,\n roomClass: T,\n defaultOptions?: OnCreateOptions<T>,\n ): RegisteredHandler\n public define<T extends Type<Room>>(\n nameOrHandler: string | T,\n handlerOrOptions: T | OnCreateOptions<T>,\n defaultOptions?: OnCreateOptions<T>,\n ): RegisteredHandler {\n const name = (typeof(nameOrHandler) === \"string\")\n ? nameOrHandler\n : nameOrHandler.name;\n\n const roomClass = (typeof(nameOrHandler) === \"string\")\n ? handlerOrOptions\n : nameOrHandler;\n\n const options = (typeof(nameOrHandler) === \"string\")\n ? defaultOptions\n : handlerOrOptions;\n\n return matchMaker.defineRoomType(name, roomClass, options);\n }\n\n /**\n * Remove a room definition from matchmaking.\n * This method does not destroy any room. It only dissallows matchmaking\n */\n public removeRoomType(name: string): void {\n matchMaker.removeRoomType(name);\n }\n\n public async gracefullyShutdown(exit: boolean = true, err?: Error) {\n if (matchMaker.state === matchMaker.MatchMakerState.SHUTTING_DOWN) {\n return;\n }\n\n try {\n // custom \"before shutdown\" method\n await this.onBeforeShutdownCallback();\n\n // this is going to lock all rooms and wait for them to be disposed\n await matchMaker.gracefullyShutdown();\n\n this.transport.shutdown();\n this.presence.shutdown();\n await this.driver.shutdown();\n\n // custom \"after shutdown\" method\n await this.onShutdownCallback();\n\n } catch (e) {\n debugAndPrintError(`error during shutdown: ${e}`);\n\n } finally {\n if (exit) {\n process.exit((err && !isDevMode) ? 1 : 0);\n }\n }\n }\n\n /**\n * Add simulated latency between client and server.\n * @param milliseconds round trip latency in milliseconds.\n */\n public simulateLatency(milliseconds: number) {\n if (milliseconds > 0) {\n logger.warn(`\uD83D\uDCF6\uFE0F\u2757 Colyseus latency simulation enabled \u2192 ${milliseconds}ms latency for round trip.`);\n } else {\n logger.warn(`\uD83D\uDCF6\uFE0F\u2757 Colyseus latency simulation disabled.`);\n }\n\n const halfwayMS = (milliseconds / 2);\n this.transport.simulateLatency(halfwayMS);\n\n if (this._originalRoomOnMessage == null) {\n this._originalRoomOnMessage = Room.prototype['_onMessage'];\n }\n\n const originalOnMessage = this._originalRoomOnMessage;\n\n Room.prototype['_onMessage'] = milliseconds <= Number.EPSILON ? originalOnMessage : function (this: Room, client, buffer) {\n // uWebSockets.js: duplicate buffer because it is cleared at native layer before the timeout.\n const cachedBuffer = Buffer.from(buffer);\n setTimeout(() => originalOnMessage.call(this, client, cachedBuffer), halfwayMS);\n };\n }\n\n /**\n * Register a callback that is going to be executed before the server shuts down.\n * @param callback\n */\n public onShutdown(callback: () => void | Promise<any>) {\n this.onShutdownCallback = callback;\n }\n\n public onBeforeShutdown(callback: () => void | Promise<any>) {\n this.onBeforeShutdownCallback = callback;\n }\n\n protected async getDefaultTransport(options: any): Promise<Transport> {\n try {\n const module = await import('@colyseus/ws-transport');\n const WebSocketTransport = module.WebSocketTransport;\n return new WebSocketTransport(options);\n\n } catch (error) {\n this._onTransportReady.reject(error);\n throw new Error(\"Please provide a 'transport' layer. Default transport not set.\");\n }\n }\n\n protected onShutdownCallback: () => void | Promise<any> =\n () => Promise.resolve()\n\n protected onBeforeShutdownCallback: () => void | Promise<any> =\n () => Promise.resolve()\n}\n\nexport type DefineServerOptions<\n T extends Record<string, RegisteredHandler>,\n R extends Router\n> = ServerOptions & {\n rooms: T,\n routes?: R,\n};\n\nexport function defineServer<\n T extends Record<string, RegisteredHandler>,\n R extends Router\n>(\n options: DefineServerOptions<T, R>,\n): Server<T, R> {\n const { rooms, routes, ...serverOptions } = options;\n const server = new Server<T, R>(serverOptions);\n\n server.router = routes;\n\n for (const [name, handler] of Object.entries(rooms)) {\n handler.name = name;\n matchMaker.addRoomType(handler);\n }\n\n return server;\n}\n\nexport function defineRoom<T extends Type<Room>>(\n roomKlass: T,\n defaultOptions?: Parameters<NonNullable<InstanceType<T>['onCreate']>>[0],\n): RegisteredHandler<InstanceType<T>> {\n return new RegisteredHandler(roomKlass, defaultOptions) as unknown as RegisteredHandler<InstanceType<T>>;\n}"],
|
|
5
|
-
"mappings": ";AAAA,SAAS,aAAa;AAGtB,SAAS,0BAA0B;AACnC,YAAY,gBAAgB;AAC5B,SAAS,yBAAyB;AAElC,SAA+B,YAAY;AAC3C,SAAS,UAAU,
|
|
4
|
+
"sourcesContent": ["import { greet } from \"@colyseus/greeting-banner\";\nimport type express from 'express';\n\nimport { debugAndPrintError } from './Debug.ts';\nimport * as matchMaker from './MatchMaker.ts';\nimport { RegisteredHandler } from './matchmaker/RegisteredHandler.ts';\n\nimport { type OnCreateOptions, Room } from './Room.ts';\nimport { Deferred, registerGracefulShutdown, dynamicImport, type Type } from './utils/Utils.ts';\n\nimport type { Presence } from \"./presence/Presence.ts\";\nimport { LocalPresence } from './presence/LocalPresence.ts';\nimport { LocalDriver } from './matchmaker/LocalDriver/LocalDriver.ts';\n\nimport { setTransport, Transport } from './Transport.ts';\nimport { logger, setLogger } from './Logger.ts';\nimport { setDevMode, isDevMode } from './utils/DevMode.ts';\nimport { type Router, bindRouterToTransport } from './router/index.ts';\nimport { type SDKTypes as SharedSDKTypes } from '@colyseus/shared-types';\nimport { getDefaultRouter } from './router/default_routes.ts';\n\nexport type ServerOptions = {\n publicAddress?: string,\n presence?: Presence,\n driver?: matchMaker.MatchMakerDriver,\n transport?: Transport,\n gracefullyShutdown?: boolean,\n logger?: any;\n\n /**\n * Optional callback to execute before the server listens.\n * This is useful for example to connect into a database or other services before the server listens.\n */\n beforeListen?: () => Promise<void> | void,\n\n /**\n * Optional callback to configure Express routes.\n * When provided, the transport layer will initialize an Express-compatible app\n * and pass it to this callback for custom route configuration.\n *\n * For uWebSockets transport, this uses the uwebsockets-express module.\n */\n express?: (app: express.Application) => void,\n\n /**\n * Custom function to determine which process should handle room creation.\n * Default: assign new rooms the process with least amount of rooms created\n */\n selectProcessIdToCreateRoom?: matchMaker.SelectProcessIdCallback;\n\n /**\n * If enabled, rooms are going to be restored in the server-side upon restart,\n * clients are going to automatically re-connect when server reboots.\n *\n * Beware of \"schema mismatch\" issues. When updating Schema structures and\n * reloading existing data, you may see \"schema mismatch\" errors in the\n * client-side.\n *\n * (This operation is costly and should not be used in a production\n * environment)\n */\n devMode?: boolean,\n\n /**\n * Display greeting message on server start.\n * Default: true\n */\n greet?: boolean,\n};\n\n/**\n * Exposed types for the client-side SDK.\n * Re-exported from @colyseus/shared-types with specific type constraints.\n */\nexport interface SDKTypes<\n RoomTypes extends Record<string, RegisteredHandler> = any,\n Routes extends Router = any\n> extends SharedSDKTypes<RoomTypes, Routes> {}\n\nexport class Server<\n RoomTypes extends Record<string, RegisteredHandler> = any,\n Routes extends Router = any\n> implements SDKTypes<RoomTypes, Routes> {\n '~rooms': RoomTypes;\n '~routes': Routes;\n\n public transport: Transport;\n public router: Routes;\n public options: ServerOptions;\n\n protected presence: Presence;\n protected driver: matchMaker.MatchMakerDriver;\n\n protected port: number | string;\n protected greet: boolean;\n\n protected _onTransportReady = new Deferred<Transport>();\n\n private _originalRoomOnMessage: typeof Room.prototype['_onMessage'] | null = null;\n\n constructor(options: ServerOptions = {}) {\n const {\n gracefullyShutdown = true,\n greet = true\n } = options;\n\n setDevMode(options.devMode === true);\n\n this.presence = options.presence || new LocalPresence();\n this.driver = options.driver || new LocalDriver();\n this.options = options;\n this.greet = greet;\n\n this.attach(options);\n\n matchMaker.setup(\n this.presence,\n this.driver,\n options.publicAddress,\n options.selectProcessIdToCreateRoom,\n );\n\n if (gracefullyShutdown) {\n registerGracefulShutdown((err) => this.gracefullyShutdown(true, err));\n }\n\n if (options.logger) {\n setLogger(options.logger);\n }\n }\n\n public async attach(options: ServerOptions) {\n this.transport = options.transport || await this.getDefaultTransport(options);\n\n // Initialize Express if callback is provided\n if (options.express && this.transport.getExpressApp) {\n const expressApp = await this.transport.getExpressApp();\n options.express(expressApp);\n }\n\n // Resolve the promise when the transport is ready\n this._onTransportReady.resolve(this.transport);\n }\n\n /**\n * Bind the server into the port specified.\n *\n * @param port - Port number or Unix socket path\n * @param hostname\n * @param backlog\n * @param listeningListener\n */\n public async listen(port: number | string, hostname?: string, backlog?: number, listeningListener?: Function) {\n if (this.options.beforeListen) {\n await this.options.beforeListen();\n }\n\n //\n // if Colyseus Cloud is detected, use @colyseus/tools to listen\n //\n if (process.env.COLYSEUS_CLOUD !== undefined ) {\n if (typeof(hostname) === \"number\") {\n //\n // workaround, @colyseus/tools calls server.listen() again with the port as a string\n //\n hostname = undefined;\n\n } else {\n try {\n return (await dynamicImport(\"@colyseus/tools\")).listen(this);\n } catch (error) {\n const err = new Error(\"Please install @colyseus/tools to be able to host on Colyseus Cloud.\");\n err.cause = error;\n throw err;\n }\n }\n }\n\n //\n // otherwise, listen on the port directly\n //\n this.port = port;\n\n //\n // Make sure matchmaker is ready before accepting connections\n // (isDevMode: matchmaker may take extra milliseconds to restore the rooms)\n //\n await matchMaker.accept();\n\n /**\n * Greetings!\n */\n if (this.greet) {\n greet();\n }\n\n // Wait for the transport to be ready\n await this._onTransportReady;\n\n return new Promise<void>((resolve, reject) => {\n // TODO: refactor me!\n // set transport globally, to be used by matchmaking route\n setTransport(this.transport);\n\n this.transport.listen(port, hostname, backlog, (err) => {\n if (this.transport.server) {\n this.transport.server.on('error', (err) => reject(err));\n }\n\n // default router is used if no router is provided\n if (!this.router) {\n this.router = getDefaultRouter() as unknown as Routes;\n\n } else {\n // make sure default routes are included\n // https://github.com/Bekacru/better-call/pull/67\n this.router = this.router.extend({ ...getDefaultRouter().endpoints }) as unknown as Routes;\n }\n\n bindRouterToTransport(this.transport, this.router);\n\n if (listeningListener) {\n listeningListener(err);\n }\n\n if (err) {\n reject(err);\n\n } else {\n resolve();\n }\n });\n });\n }\n\n /**\n * Define a new type of room for matchmaking.\n *\n * @param name public room identifier for match-making.\n * @param roomClass Room class definition\n * @param defaultOptions default options for `onCreate`\n */\n public define<T extends Type<Room>>(\n roomClass: T,\n defaultOptions?: OnCreateOptions<T>,\n ): RegisteredHandler\n public define<T extends Type<Room>>(\n name: string,\n roomClass: T,\n defaultOptions?: OnCreateOptions<T>,\n ): RegisteredHandler\n public define<T extends Type<Room>>(\n nameOrHandler: string | T,\n handlerOrOptions: T | OnCreateOptions<T>,\n defaultOptions?: OnCreateOptions<T>,\n ): RegisteredHandler {\n const name = (typeof(nameOrHandler) === \"string\")\n ? nameOrHandler\n : nameOrHandler.name;\n\n const roomClass = (typeof(nameOrHandler) === \"string\")\n ? handlerOrOptions\n : nameOrHandler;\n\n const options = (typeof(nameOrHandler) === \"string\")\n ? defaultOptions\n : handlerOrOptions;\n\n return matchMaker.defineRoomType(name, roomClass, options);\n }\n\n /**\n * Remove a room definition from matchmaking.\n * This method does not destroy any room. It only dissallows matchmaking\n */\n public removeRoomType(name: string): void {\n matchMaker.removeRoomType(name);\n }\n\n public async gracefullyShutdown(exit: boolean = true, err?: Error) {\n if (matchMaker.state === matchMaker.MatchMakerState.SHUTTING_DOWN) {\n return;\n }\n\n try {\n // custom \"before shutdown\" method\n await this.onBeforeShutdownCallback();\n\n // this is going to lock all rooms and wait for them to be disposed\n await matchMaker.gracefullyShutdown();\n\n this.transport.shutdown();\n this.presence.shutdown();\n await this.driver.shutdown();\n\n // custom \"after shutdown\" method\n await this.onShutdownCallback();\n\n } catch (e) {\n debugAndPrintError(`error during shutdown: ${e}`);\n\n } finally {\n if (exit) {\n process.exit((err && !isDevMode) ? 1 : 0);\n }\n }\n }\n\n /**\n * Add simulated latency between client and server.\n * @param milliseconds round trip latency in milliseconds.\n */\n public simulateLatency(milliseconds: number) {\n if (milliseconds > 0) {\n logger.warn(`\uD83D\uDCF6\uFE0F\u2757 Colyseus latency simulation enabled \u2192 ${milliseconds}ms latency for round trip.`);\n } else {\n logger.warn(`\uD83D\uDCF6\uFE0F\u2757 Colyseus latency simulation disabled.`);\n }\n\n const halfwayMS = (milliseconds / 2);\n this.transport.simulateLatency(halfwayMS);\n\n if (this._originalRoomOnMessage == null) {\n this._originalRoomOnMessage = Room.prototype['_onMessage'];\n }\n\n const originalOnMessage = this._originalRoomOnMessage;\n\n Room.prototype['_onMessage'] = milliseconds <= Number.EPSILON ? originalOnMessage : function (this: Room, client, buffer) {\n // uWebSockets.js: duplicate buffer because it is cleared at native layer before the timeout.\n const cachedBuffer = Buffer.from(buffer);\n setTimeout(() => originalOnMessage.call(this, client, cachedBuffer), halfwayMS);\n };\n }\n\n /**\n * Register a callback that is going to be executed before the server shuts down.\n * @param callback\n */\n public onShutdown(callback: () => void | Promise<any>) {\n this.onShutdownCallback = callback;\n }\n\n public onBeforeShutdown(callback: () => void | Promise<any>) {\n this.onBeforeShutdownCallback = callback;\n }\n\n protected async getDefaultTransport(options: any): Promise<Transport> {\n try {\n const module = await dynamicImport('@colyseus/ws-transport');\n const WebSocketTransport = module.WebSocketTransport;\n return new WebSocketTransport(options);\n\n } catch (error) {\n this._onTransportReady.reject(error);\n throw new Error(\"Please provide a 'transport' layer. Default transport not set.\");\n }\n }\n\n protected onShutdownCallback: () => void | Promise<any> =\n () => Promise.resolve()\n\n protected onBeforeShutdownCallback: () => void | Promise<any> =\n () => Promise.resolve()\n}\n\nexport type DefineServerOptions<\n T extends Record<string, RegisteredHandler>,\n R extends Router\n> = ServerOptions & {\n rooms: T,\n routes?: R,\n};\n\nexport function defineServer<\n T extends Record<string, RegisteredHandler>,\n R extends Router\n>(\n options: DefineServerOptions<T, R>,\n): Server<T, R> {\n const { rooms, routes, ...serverOptions } = options;\n const server = new Server<T, R>(serverOptions);\n\n server.router = routes;\n\n for (const [name, handler] of Object.entries(rooms)) {\n handler.name = name;\n matchMaker.addRoomType(handler);\n }\n\n return server;\n}\n\nexport function defineRoom<T extends Type<Room>>(\n roomKlass: T,\n defaultOptions?: Parameters<NonNullable<InstanceType<T>['onCreate']>>[0],\n): RegisteredHandler<InstanceType<T>> {\n return new RegisteredHandler(roomKlass, defaultOptions) as unknown as RegisteredHandler<InstanceType<T>>;\n}"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["gracefullyShutdown", "greet", "err"]
|
|
7
7
|
}
|
package/build/index.cjs
CHANGED
|
@@ -38,7 +38,6 @@ __export(index_exports, {
|
|
|
38
38
|
Deferred: () => import_Utils.Deferred,
|
|
39
39
|
Delayed: () => import_timer.Delayed,
|
|
40
40
|
ErrorCode: () => import_shared_types.ErrorCode,
|
|
41
|
-
HttpServerMock: () => import_Utils.HttpServerMock,
|
|
42
41
|
LobbyRoom: () => import_LobbyRoom.LobbyRoom,
|
|
43
42
|
LocalPresence: () => import_LocalPresence.LocalPresence,
|
|
44
43
|
OnAuthException: () => import_RoomExceptions.OnAuthException,
|
|
@@ -75,6 +74,7 @@ __export(index_exports, {
|
|
|
75
74
|
debugPresence: () => import_Debug.debugPresence,
|
|
76
75
|
defineRoom: () => import_Server.defineRoom,
|
|
77
76
|
defineServer: () => import_Server.defineServer,
|
|
77
|
+
dynamicImport: () => import_Utils.dynamicImport,
|
|
78
78
|
generateId: () => import_Utils.generateId,
|
|
79
79
|
getBearerToken: () => import_Utils.getBearerToken,
|
|
80
80
|
getMessageBytes: () => import_Protocol.getMessageBytes,
|
|
@@ -127,7 +127,6 @@ var import_Logger = require("./Logger.cjs");
|
|
|
127
127
|
Deferred,
|
|
128
128
|
Delayed,
|
|
129
129
|
ErrorCode,
|
|
130
|
-
HttpServerMock,
|
|
131
130
|
LobbyRoom,
|
|
132
131
|
LocalPresence,
|
|
133
132
|
OnAuthException,
|
|
@@ -164,6 +163,7 @@ var import_Logger = require("./Logger.cjs");
|
|
|
164
163
|
debugPresence,
|
|
165
164
|
defineRoom,
|
|
166
165
|
defineServer,
|
|
166
|
+
dynamicImport,
|
|
167
167
|
generateId,
|
|
168
168
|
getBearerToken,
|
|
169
169
|
getMessageBytes,
|
package/build/index.cjs.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/index.ts"],
|
|
4
|
-
"sourcesContent": ["import { ClockTimer as Clock, Delayed } from '@colyseus/timer';\n\n// Shared types - re-export from @colyseus/shared-types for convenience\nexport {\n Protocol,\n ErrorCode,\n CloseCode,\n type InferState,\n type ExtractRoomMessages,\n type ExtractRoomClientMessages,\n} from '@colyseus/shared-types';\n\n// Core classes\nexport { Server, defineRoom, defineServer, type ServerOptions, type SDKTypes } from './Server.ts';\nexport { Room, room, RoomInternalState, validate, type RoomOptions, type MessageHandlerWithFormat, type Messages, type ExtractRoomState, type ExtractRoomMetadata, type ExtractRoomClient } from './Room.ts';\nexport { getMessageBytes } from './Protocol.ts';\nexport { RegisteredHandler } from './matchmaker/RegisteredHandler.ts';\nexport { ServerError } from './errors/ServerError.ts';\n\nexport {\n type RoomException,\n type RoomMethodName,\n OnCreateException,\n OnAuthException,\n OnJoinException,\n OnLeaveException,\n OnDisposeException,\n OnMessageException,\n SimulationIntervalException,\n TimedEventException,\n} from './errors/RoomExceptions.ts';\n\n// MatchMaker\nimport * as matchMaker from './MatchMaker.ts';\nexport { matchMaker };\nexport { updateLobby, subscribeLobby } from './matchmaker/Lobby.ts';\n\n// Driver\nexport * from './matchmaker/LocalDriver/LocalDriver.ts';\nexport { initializeRoomCache } from './matchmaker/driver.ts';\n\n// Transport\nexport { type Client, type ClientPrivate, type AuthContext, ClientState, ClientArray, Transport, type ISendOptions, connectClientToRoom } from './Transport.ts';\n\n// Presence\nexport { type Presence } from './presence/Presence.ts';\nexport { LocalPresence } from './presence/LocalPresence.ts';\n\n// Serializers\nexport { type Serializer } from './serializer/Serializer.ts';\nexport { SchemaSerializer } from './serializer/SchemaSerializer.ts';\n\n// Utilities\nexport { Clock, Delayed };\nexport { generateId, Deferred,
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA,4BAAAA;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAA6C;AAG7C,0BAOO;AAGP,oBAAoF;AACpF,kBAAiM;AACjM,sBAAgC;AAChC,+BAAkC;AAClC,yBAA4B;AAE5B,4BAWO;AAGP,iBAA4B;AAE5B,mBAA4C;AAG5C,0BAAc,qDAtCd;AAuCA,oBAAoC;AAGpC,uBAA+I;AAG/I,sBAA8B;AAC9B,2BAA8B;AAG9B,wBAAgC;AAChC,8BAAiC;AAIjC,
|
|
4
|
+
"sourcesContent": ["import { ClockTimer as Clock, Delayed } from '@colyseus/timer';\n\n// Shared types - re-export from @colyseus/shared-types for convenience\nexport {\n Protocol,\n ErrorCode,\n CloseCode,\n type InferState,\n type ExtractRoomMessages,\n type ExtractRoomClientMessages,\n} from '@colyseus/shared-types';\n\n// Core classes\nexport { Server, defineRoom, defineServer, type ServerOptions, type SDKTypes } from './Server.ts';\nexport { Room, room, RoomInternalState, validate, type RoomOptions, type MessageHandlerWithFormat, type Messages, type ExtractRoomState, type ExtractRoomMetadata, type ExtractRoomClient } from './Room.ts';\nexport { getMessageBytes } from './Protocol.ts';\nexport { RegisteredHandler } from './matchmaker/RegisteredHandler.ts';\nexport { ServerError } from './errors/ServerError.ts';\n\nexport {\n type RoomException,\n type RoomMethodName,\n OnCreateException,\n OnAuthException,\n OnJoinException,\n OnLeaveException,\n OnDisposeException,\n OnMessageException,\n SimulationIntervalException,\n TimedEventException,\n} from './errors/RoomExceptions.ts';\n\n// MatchMaker\nimport * as matchMaker from './MatchMaker.ts';\nexport { matchMaker };\nexport { updateLobby, subscribeLobby } from './matchmaker/Lobby.ts';\n\n// Driver\nexport * from './matchmaker/LocalDriver/LocalDriver.ts';\nexport { initializeRoomCache } from './matchmaker/driver.ts';\n\n// Transport\nexport { type Client, type ClientPrivate, type AuthContext, ClientState, ClientArray, Transport, type ISendOptions, connectClientToRoom } from './Transport.ts';\n\n// Presence\nexport { type Presence } from './presence/Presence.ts';\nexport { LocalPresence } from './presence/LocalPresence.ts';\n\n// Serializers\nexport { type Serializer } from './serializer/Serializer.ts';\nexport { SchemaSerializer } from './serializer/SchemaSerializer.ts';\n\n// Utilities\nexport { Clock, Delayed };\nexport { generateId, Deferred, spliceOne, getBearerToken, dynamicImport } from './utils/Utils.ts';\nexport { isDevMode } from './utils/DevMode.ts';\n\n// IPC\nexport { subscribeIPC, requestFromIPC } from './IPC.ts';\n\n// Debug\nexport {\n debugMatchMaking,\n debugMessage,\n debugPatch,\n debugError,\n debugConnection,\n debugDriver,\n debugPresence,\n debugAndPrintError,\n} from './Debug.ts';\n\n// Default rooms\nexport { LobbyRoom } from './rooms/LobbyRoom.ts';\nexport { RelayRoom } from './rooms/RelayRoom.ts';\nexport { QueueRoom, type QueueOptions, type QueueMatchGroup, type QueueMatchTeam, type QueueClientData } from './rooms/QueueRoom.ts';\n\n// Router / Endpoints\nexport {\n createEndpoint,\n createInternalContext,\n createMiddleware,\n createRouter,\n toNodeHandler,\n __globalEndpoints,\n type Router,\n type RouterConfig,\n type Endpoint,\n type EndpointHandler,\n type EndpointOptions,\n type EndpointContext,\n type StrictEndpoint,\n} from './router/index.ts';\n\n// Abstract logging support\nexport { logger } from './Logger.ts';\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA,4BAAAA;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAA6C;AAG7C,0BAOO;AAGP,oBAAoF;AACpF,kBAAiM;AACjM,sBAAgC;AAChC,+BAAkC;AAClC,yBAA4B;AAE5B,4BAWO;AAGP,iBAA4B;AAE5B,mBAA4C;AAG5C,0BAAc,qDAtCd;AAuCA,oBAAoC;AAGpC,uBAA+I;AAG/I,sBAA8B;AAC9B,2BAA8B;AAG9B,wBAAgC;AAChC,8BAAiC;AAIjC,mBAA+E;AAC/E,qBAA0B;AAG1B,iBAA6C;AAG7C,mBASO;AAGP,uBAA0B;AAC1B,uBAA0B;AAC1B,uBAA8G;AAG9G,oBAcO;AAGP,oBAAuB;",
|
|
6
6
|
"names": ["Clock"]
|
|
7
7
|
}
|
package/build/index.d.ts
CHANGED
|
@@ -17,7 +17,7 @@ export { LocalPresence } from './presence/LocalPresence.ts';
|
|
|
17
17
|
export { type Serializer } from './serializer/Serializer.ts';
|
|
18
18
|
export { SchemaSerializer } from './serializer/SchemaSerializer.ts';
|
|
19
19
|
export { Clock, Delayed };
|
|
20
|
-
export { generateId, Deferred,
|
|
20
|
+
export { generateId, Deferred, spliceOne, getBearerToken, dynamicImport } from './utils/Utils.ts';
|
|
21
21
|
export { isDevMode } from './utils/DevMode.ts';
|
|
22
22
|
export { subscribeIPC, requestFromIPC } from './IPC.ts';
|
|
23
23
|
export { debugMatchMaking, debugMessage, debugPatch, debugError, debugConnection, debugDriver, debugPresence, debugAndPrintError, } from './Debug.ts';
|
package/build/index.mjs
CHANGED
|
@@ -29,7 +29,7 @@ import {} from "./presence/Presence.mjs";
|
|
|
29
29
|
import { LocalPresence } from "./presence/LocalPresence.mjs";
|
|
30
30
|
import {} from "./serializer/Serializer.mjs";
|
|
31
31
|
import { SchemaSerializer } from "./serializer/SchemaSerializer.mjs";
|
|
32
|
-
import { generateId, Deferred,
|
|
32
|
+
import { generateId, Deferred, spliceOne, getBearerToken, dynamicImport } from "./utils/Utils.mjs";
|
|
33
33
|
import { isDevMode } from "./utils/DevMode.mjs";
|
|
34
34
|
import { subscribeIPC, requestFromIPC } from "./IPC.mjs";
|
|
35
35
|
import {
|
|
@@ -62,7 +62,6 @@ export {
|
|
|
62
62
|
Deferred,
|
|
63
63
|
Delayed,
|
|
64
64
|
ErrorCode,
|
|
65
|
-
HttpServerMock,
|
|
66
65
|
LobbyRoom,
|
|
67
66
|
LocalPresence,
|
|
68
67
|
OnAuthException,
|
|
@@ -99,6 +98,7 @@ export {
|
|
|
99
98
|
debugPresence,
|
|
100
99
|
defineRoom,
|
|
101
100
|
defineServer,
|
|
101
|
+
dynamicImport,
|
|
102
102
|
generateId,
|
|
103
103
|
getBearerToken,
|
|
104
104
|
getMessageBytes,
|
package/build/index.mjs.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/index.ts"],
|
|
4
|
-
"sourcesContent": ["import { ClockTimer as Clock, Delayed } from '@colyseus/timer';\n\n// Shared types - re-export from @colyseus/shared-types for convenience\nexport {\n Protocol,\n ErrorCode,\n CloseCode,\n type InferState,\n type ExtractRoomMessages,\n type ExtractRoomClientMessages,\n} from '@colyseus/shared-types';\n\n// Core classes\nexport { Server, defineRoom, defineServer, type ServerOptions, type SDKTypes } from './Server.ts';\nexport { Room, room, RoomInternalState, validate, type RoomOptions, type MessageHandlerWithFormat, type Messages, type ExtractRoomState, type ExtractRoomMetadata, type ExtractRoomClient } from './Room.ts';\nexport { getMessageBytes } from './Protocol.ts';\nexport { RegisteredHandler } from './matchmaker/RegisteredHandler.ts';\nexport { ServerError } from './errors/ServerError.ts';\n\nexport {\n type RoomException,\n type RoomMethodName,\n OnCreateException,\n OnAuthException,\n OnJoinException,\n OnLeaveException,\n OnDisposeException,\n OnMessageException,\n SimulationIntervalException,\n TimedEventException,\n} from './errors/RoomExceptions.ts';\n\n// MatchMaker\nimport * as matchMaker from './MatchMaker.ts';\nexport { matchMaker };\nexport { updateLobby, subscribeLobby } from './matchmaker/Lobby.ts';\n\n// Driver\nexport * from './matchmaker/LocalDriver/LocalDriver.ts';\nexport { initializeRoomCache } from './matchmaker/driver.ts';\n\n// Transport\nexport { type Client, type ClientPrivate, type AuthContext, ClientState, ClientArray, Transport, type ISendOptions, connectClientToRoom } from './Transport.ts';\n\n// Presence\nexport { type Presence } from './presence/Presence.ts';\nexport { LocalPresence } from './presence/LocalPresence.ts';\n\n// Serializers\nexport { type Serializer } from './serializer/Serializer.ts';\nexport { SchemaSerializer } from './serializer/SchemaSerializer.ts';\n\n// Utilities\nexport { Clock, Delayed };\nexport { generateId, Deferred,
|
|
5
|
-
"mappings": ";AAAA,SAAS,cAAc,OAAO,eAAe;AAG7C;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OAIK;AAGP,SAAS,QAAQ,YAAY,oBAAuD;AACpF,SAAS,MAAM,MAAM,mBAAmB,gBAAyJ;AACjM,SAAS,uBAAuB;AAChC,SAAS,yBAAyB;AAClC,SAAS,mBAAmB;AAE5B;AAAA,EAGE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAGP,YAAY,gBAAgB;AAE5B,SAAS,aAAa,sBAAsB;AAG5C,cAAc;AACd,SAAS,2BAA2B;AAGpC,SAA4D,aAAa,aAAa,WAA8B,2BAA2B;AAG/I,eAA8B;AAC9B,SAAS,qBAAqB;AAG9B,eAAgC;AAChC,SAAS,wBAAwB;AAIjC,SAAS,YAAY,UAAU,gBAAgB,
|
|
4
|
+
"sourcesContent": ["import { ClockTimer as Clock, Delayed } from '@colyseus/timer';\n\n// Shared types - re-export from @colyseus/shared-types for convenience\nexport {\n Protocol,\n ErrorCode,\n CloseCode,\n type InferState,\n type ExtractRoomMessages,\n type ExtractRoomClientMessages,\n} from '@colyseus/shared-types';\n\n// Core classes\nexport { Server, defineRoom, defineServer, type ServerOptions, type SDKTypes } from './Server.ts';\nexport { Room, room, RoomInternalState, validate, type RoomOptions, type MessageHandlerWithFormat, type Messages, type ExtractRoomState, type ExtractRoomMetadata, type ExtractRoomClient } from './Room.ts';\nexport { getMessageBytes } from './Protocol.ts';\nexport { RegisteredHandler } from './matchmaker/RegisteredHandler.ts';\nexport { ServerError } from './errors/ServerError.ts';\n\nexport {\n type RoomException,\n type RoomMethodName,\n OnCreateException,\n OnAuthException,\n OnJoinException,\n OnLeaveException,\n OnDisposeException,\n OnMessageException,\n SimulationIntervalException,\n TimedEventException,\n} from './errors/RoomExceptions.ts';\n\n// MatchMaker\nimport * as matchMaker from './MatchMaker.ts';\nexport { matchMaker };\nexport { updateLobby, subscribeLobby } from './matchmaker/Lobby.ts';\n\n// Driver\nexport * from './matchmaker/LocalDriver/LocalDriver.ts';\nexport { initializeRoomCache } from './matchmaker/driver.ts';\n\n// Transport\nexport { type Client, type ClientPrivate, type AuthContext, ClientState, ClientArray, Transport, type ISendOptions, connectClientToRoom } from './Transport.ts';\n\n// Presence\nexport { type Presence } from './presence/Presence.ts';\nexport { LocalPresence } from './presence/LocalPresence.ts';\n\n// Serializers\nexport { type Serializer } from './serializer/Serializer.ts';\nexport { SchemaSerializer } from './serializer/SchemaSerializer.ts';\n\n// Utilities\nexport { Clock, Delayed };\nexport { generateId, Deferred, spliceOne, getBearerToken, dynamicImport } from './utils/Utils.ts';\nexport { isDevMode } from './utils/DevMode.ts';\n\n// IPC\nexport { subscribeIPC, requestFromIPC } from './IPC.ts';\n\n// Debug\nexport {\n debugMatchMaking,\n debugMessage,\n debugPatch,\n debugError,\n debugConnection,\n debugDriver,\n debugPresence,\n debugAndPrintError,\n} from './Debug.ts';\n\n// Default rooms\nexport { LobbyRoom } from './rooms/LobbyRoom.ts';\nexport { RelayRoom } from './rooms/RelayRoom.ts';\nexport { QueueRoom, type QueueOptions, type QueueMatchGroup, type QueueMatchTeam, type QueueClientData } from './rooms/QueueRoom.ts';\n\n// Router / Endpoints\nexport {\n createEndpoint,\n createInternalContext,\n createMiddleware,\n createRouter,\n toNodeHandler,\n __globalEndpoints,\n type Router,\n type RouterConfig,\n type Endpoint,\n type EndpointHandler,\n type EndpointOptions,\n type EndpointContext,\n type StrictEndpoint,\n} from './router/index.ts';\n\n// Abstract logging support\nexport { logger } from './Logger.ts';\n"],
|
|
5
|
+
"mappings": ";AAAA,SAAS,cAAc,OAAO,eAAe;AAG7C;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OAIK;AAGP,SAAS,QAAQ,YAAY,oBAAuD;AACpF,SAAS,MAAM,MAAM,mBAAmB,gBAAyJ;AACjM,SAAS,uBAAuB;AAChC,SAAS,yBAAyB;AAClC,SAAS,mBAAmB;AAE5B;AAAA,EAGE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAGP,YAAY,gBAAgB;AAE5B,SAAS,aAAa,sBAAsB;AAG5C,cAAc;AACd,SAAS,2BAA2B;AAGpC,SAA4D,aAAa,aAAa,WAA8B,2BAA2B;AAG/I,eAA8B;AAC9B,SAAS,qBAAqB;AAG9B,eAAgC;AAChC,SAAS,wBAAwB;AAIjC,SAAS,YAAY,UAAU,WAAW,gBAAgB,qBAAqB;AAC/E,SAAS,iBAAiB;AAG1B,SAAS,cAAc,sBAAsB;AAG7C;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAGP,SAAS,iBAAiB;AAC1B,SAAS,iBAAiB;AAC1B,SAAS,iBAAqG;AAG9G;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAQK;AAGP,SAAS,cAAc;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/build/utils/Utils.cjs
CHANGED
|
@@ -21,9 +21,9 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
21
21
|
var Utils_exports = {};
|
|
22
22
|
__export(Utils_exports, {
|
|
23
23
|
Deferred: () => Deferred,
|
|
24
|
-
HttpServerMock: () => HttpServerMock,
|
|
25
24
|
MAX_CONCURRENT_CREATE_ROOM_WAIT_TIME: () => MAX_CONCURRENT_CREATE_ROOM_WAIT_TIME,
|
|
26
25
|
REMOTE_ROOM_SHORT_TIMEOUT: () => REMOTE_ROOM_SHORT_TIMEOUT,
|
|
26
|
+
dynamicImport: () => dynamicImport,
|
|
27
27
|
generateId: () => generateId,
|
|
28
28
|
getBearerToken: () => getBearerToken,
|
|
29
29
|
merge: () => merge,
|
|
@@ -34,7 +34,6 @@ __export(Utils_exports, {
|
|
|
34
34
|
});
|
|
35
35
|
module.exports = __toCommonJS(Utils_exports);
|
|
36
36
|
var import_nanoid = require("nanoid");
|
|
37
|
-
var import_events = require("events");
|
|
38
37
|
var import_RoomExceptions = require("../errors/RoomExceptions.cjs");
|
|
39
38
|
var import_Debug = require("../Debug.cjs");
|
|
40
39
|
var REMOTE_ROOM_SHORT_TIMEOUT = Number(process.env.COLYSEUS_PRESENCE_SHORT_TIMEOUT || 2e3);
|
|
@@ -130,14 +129,26 @@ function wrapTryCatch(method, onError, exceptionClass, methodName, rethrow = fal
|
|
|
130
129
|
}
|
|
131
130
|
};
|
|
132
131
|
}
|
|
133
|
-
|
|
134
|
-
|
|
132
|
+
function dynamicImport(moduleName) {
|
|
133
|
+
if (typeof __dirname !== "undefined") {
|
|
134
|
+
try {
|
|
135
|
+
return Promise.resolve(require(moduleName));
|
|
136
|
+
} catch (e) {
|
|
137
|
+
return Promise.reject(e.code !== "MODULE_NOT_FOUND" ? e : void 0);
|
|
138
|
+
}
|
|
139
|
+
} else {
|
|
140
|
+
const promise = import(moduleName);
|
|
141
|
+
promise.catch(() => {
|
|
142
|
+
});
|
|
143
|
+
return promise;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
135
146
|
// Annotate the CommonJS export names for ESM import in node:
|
|
136
147
|
0 && (module.exports = {
|
|
137
148
|
Deferred,
|
|
138
|
-
HttpServerMock,
|
|
139
149
|
MAX_CONCURRENT_CREATE_ROOM_WAIT_TIME,
|
|
140
150
|
REMOTE_ROOM_SHORT_TIMEOUT,
|
|
151
|
+
dynamicImport,
|
|
141
152
|
generateId,
|
|
142
153
|
getBearerToken,
|
|
143
154
|
merge,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/utils/Utils.ts"],
|
|
4
|
-
"sourcesContent": ["import { nanoid } from 'nanoid';\
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oBAAuB;
|
|
4
|
+
"sourcesContent": ["import { nanoid } from 'nanoid';\nimport { type RoomException, type RoomMethodName } from '../errors/RoomExceptions.ts';\n\nimport { debugAndPrintError, debugMatchMaking } from '../Debug.ts';\n\nexport type Type<T> = new (...args: any[]) => T;\nexport type MethodName<T> = string & {\n [K in keyof T]: T[K] extends (...args: any[]) => any ? K : never\n}[keyof T];\n\n/**\n * Utility type that extracts the return type of a method or the type of a property\n * from a given class/object type.\n *\n * - If the key is a method, returns the awaited return type of that method\n * - If the key is a property, returns the type of that property\n */\nexport type ExtractMethodOrPropertyType<\n TClass,\n TKey extends keyof TClass\n> = TClass[TKey] extends (...args: any[]) => infer R\n ? Awaited<R>\n : TClass[TKey];\n\n// remote room call timeouts\nexport const REMOTE_ROOM_SHORT_TIMEOUT = Number(process.env.COLYSEUS_PRESENCE_SHORT_TIMEOUT || 2000);\nexport const MAX_CONCURRENT_CREATE_ROOM_WAIT_TIME = Number(process.env.COLYSEUS_MAX_CONCURRENT_CREATE_ROOM_WAIT_TIME || 0.5);\n\nexport function generateId(length: number = 9) {\n return nanoid(length);\n}\n\nexport function getBearerToken(authHeader: string) {\n return (authHeader && authHeader.startsWith(\"Bearer \") && authHeader.substring(7, authHeader.length)) || undefined;\n}\n\n// nodemon sends SIGUSR2 before reloading\n// (https://github.com/remy/nodemon#controlling-shutdown-of-your-script)\n//\nconst signals: NodeJS.Signals[] = ['SIGINT', 'SIGTERM', 'SIGUSR2'];\n\nexport function registerGracefulShutdown(callback: (err?: Error) => void) {\n /**\n * Gracefully shutdown on uncaught errors\n */\n process.on('uncaughtException', (err) => {\n debugAndPrintError(err);\n callback(err);\n });\n\n signals.forEach((signal) =>\n process.once(signal, () => callback()));\n}\n\nexport function retry<T = any>(\n cb: Function,\n maxRetries: number = 3,\n errorWhiteList: any[] = [],\n retries: number = 0,\n) {\n return new Promise<T>((resolve, reject) => {\n cb()\n .then(resolve)\n .catch((e: any) => {\n if (\n errorWhiteList.indexOf(e.constructor) !== -1 &&\n retries++ < maxRetries\n ) {\n setTimeout(() => {\n debugMatchMaking(\"retrying due to error (error: %s, retries: %s, maxRetries: %s)\", e.message, retries, maxRetries);\n retry<T>(cb, maxRetries, errorWhiteList, retries).\n then(resolve).\n catch((e2) => reject(e2));\n }, Math.floor(Math.random() * Math.pow(2, retries) * 400));\n\n } else {\n reject(e);\n }\n });\n });\n}\n\nexport function spliceOne(arr: any[], index: number): boolean {\n // manually splice availableRooms array\n // http://jsperf.com/manual-splice\n if (index === -1 || index >= arr.length) {\n return false;\n }\n\n const len = arr.length - 1;\n for (let i = index; i < len; i++) {\n arr[i] = arr[i + 1];\n }\n\n arr.length = len;\n return true;\n}\n\nexport class Deferred<T = any> {\n public promise: Promise<T>;\n\n public resolve: Function;\n public reject: Function;\n\n constructor(promise?: Promise<T>) {\n this.promise = promise ?? new Promise<T>((resolve, reject) => {\n this.resolve = resolve;\n this.reject = reject;\n });\n }\n\n public then(onFulfilled?: (value: T) => any, onRejected?: (reason: any) => any) {\n return this.promise.then(onFulfilled, onRejected);\n }\n\n public catch(func: (value: any) => any) {\n return this.promise.catch(func);\n }\n\n static reject (reason?: any) {\n return new Deferred(Promise.reject(reason));\n }\n\n static resolve<T = any>(value?: T) {\n return new Deferred<T>(Promise.resolve(value));\n }\n\n}\n\nexport function merge(a: any, ...objs: any[]): any {\n for (let i = 0, len = objs.length; i < len; i++) {\n const b = objs[i];\n for (const key in b) {\n if (b.hasOwnProperty(key)) {\n a[key] = b[key];\n }\n }\n }\n return a;\n}\n\nexport function wrapTryCatch(\n method: Function,\n onError: (error: RoomException, methodName: RoomMethodName) => void,\n exceptionClass: Type<RoomException>,\n methodName: RoomMethodName,\n rethrow: boolean = false,\n ...additionalErrorArgs: any[]\n) {\n return (...args: any[]) => {\n try {\n const result = method(...args);\n if (typeof (result?.catch) === \"function\") {\n return result.catch((e: Error) => {\n onError(new exceptionClass(e, e.message, ...args, ...additionalErrorArgs), methodName);\n if (rethrow) { throw e; }\n });\n }\n return result;\n } catch (e: any) {\n onError(new exceptionClass(e, e.message, ...args, ...additionalErrorArgs), methodName);\n if (rethrow) { throw e; }\n }\n };\n}\n\n/**\n * Dynamically import a module using either require() or import()\n * based on the current module system (CJS vs ESM).\n *\n * This avoids double-loading packages when running in mixed ESM/CJS environments.\n * Errors are silently caught - await the promise and handle errors at usage site.\n */\nexport function dynamicImport<T = any>(moduleName: string): Promise<T> {\n // __dirname exists in CJS but not in ESM\n if (typeof __dirname !== 'undefined') {\n // CJS context - use require()\n try {\n return Promise.resolve(require(moduleName));\n } catch (e: any) {\n // If the error is not a MODULE_NOT_FOUND error, reject with the error.\n return Promise.reject((e.code !== 'MODULE_NOT_FOUND') ? e : undefined);\n }\n } else {\n // ESM context - use import()\n const promise = import(moduleName);\n promise.catch(() => {}); // prevent unhandled rejection warnings\n return promise;\n }\n}"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/build/utils/Utils.d.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { EventEmitter } from "events";
|
|
2
1
|
import { type RoomException, type RoomMethodName } from '../errors/RoomExceptions.ts';
|
|
3
2
|
export type Type<T> = new (...args: any[]) => T;
|
|
4
3
|
export type MethodName<T> = string & {
|
|
@@ -31,5 +30,11 @@ export declare class Deferred<T = any> {
|
|
|
31
30
|
}
|
|
32
31
|
export declare function merge(a: any, ...objs: any[]): any;
|
|
33
32
|
export declare function wrapTryCatch(method: Function, onError: (error: RoomException, methodName: RoomMethodName) => void, exceptionClass: Type<RoomException>, methodName: RoomMethodName, rethrow?: boolean, ...additionalErrorArgs: any[]): (...args: any[]) => any;
|
|
34
|
-
|
|
35
|
-
|
|
33
|
+
/**
|
|
34
|
+
* Dynamically import a module using either require() or import()
|
|
35
|
+
* based on the current module system (CJS vs ESM).
|
|
36
|
+
*
|
|
37
|
+
* This avoids double-loading packages when running in mixed ESM/CJS environments.
|
|
38
|
+
* Errors are silently caught - await the promise and handle errors at usage site.
|
|
39
|
+
*/
|
|
40
|
+
export declare function dynamicImport<T = any>(moduleName: string): Promise<T>;
|
package/build/utils/Utils.mjs
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
2
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
3
|
+
}) : x)(function(x) {
|
|
4
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
5
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
6
|
+
});
|
|
7
|
+
|
|
1
8
|
// packages/core/src/utils/Utils.ts
|
|
2
9
|
import { nanoid } from "nanoid";
|
|
3
|
-
import { EventEmitter } from "events";
|
|
4
10
|
import "../errors/RoomExceptions.mjs";
|
|
5
11
|
import { debugAndPrintError, debugMatchMaking } from "../Debug.mjs";
|
|
6
12
|
var REMOTE_ROOM_SHORT_TIMEOUT = Number(process.env.COLYSEUS_PRESENCE_SHORT_TIMEOUT || 2e3);
|
|
@@ -96,13 +102,25 @@ function wrapTryCatch(method, onError, exceptionClass, methodName, rethrow = fal
|
|
|
96
102
|
}
|
|
97
103
|
};
|
|
98
104
|
}
|
|
99
|
-
|
|
100
|
-
|
|
105
|
+
function dynamicImport(moduleName) {
|
|
106
|
+
if (typeof __dirname !== "undefined") {
|
|
107
|
+
try {
|
|
108
|
+
return Promise.resolve(__require(moduleName));
|
|
109
|
+
} catch (e) {
|
|
110
|
+
return Promise.reject(e.code !== "MODULE_NOT_FOUND" ? e : void 0);
|
|
111
|
+
}
|
|
112
|
+
} else {
|
|
113
|
+
const promise = import(moduleName);
|
|
114
|
+
promise.catch(() => {
|
|
115
|
+
});
|
|
116
|
+
return promise;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
101
119
|
export {
|
|
102
120
|
Deferred,
|
|
103
|
-
HttpServerMock,
|
|
104
121
|
MAX_CONCURRENT_CREATE_ROOM_WAIT_TIME,
|
|
105
122
|
REMOTE_ROOM_SHORT_TIMEOUT,
|
|
123
|
+
dynamicImport,
|
|
106
124
|
generateId,
|
|
107
125
|
getBearerToken,
|
|
108
126
|
merge,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/utils/Utils.ts"],
|
|
4
|
-
"sourcesContent": ["import { nanoid } from 'nanoid';\
|
|
5
|
-
"mappings": "
|
|
4
|
+
"sourcesContent": ["import { nanoid } from 'nanoid';\nimport { type RoomException, type RoomMethodName } from '../errors/RoomExceptions.ts';\n\nimport { debugAndPrintError, debugMatchMaking } from '../Debug.ts';\n\nexport type Type<T> = new (...args: any[]) => T;\nexport type MethodName<T> = string & {\n [K in keyof T]: T[K] extends (...args: any[]) => any ? K : never\n}[keyof T];\n\n/**\n * Utility type that extracts the return type of a method or the type of a property\n * from a given class/object type.\n *\n * - If the key is a method, returns the awaited return type of that method\n * - If the key is a property, returns the type of that property\n */\nexport type ExtractMethodOrPropertyType<\n TClass,\n TKey extends keyof TClass\n> = TClass[TKey] extends (...args: any[]) => infer R\n ? Awaited<R>\n : TClass[TKey];\n\n// remote room call timeouts\nexport const REMOTE_ROOM_SHORT_TIMEOUT = Number(process.env.COLYSEUS_PRESENCE_SHORT_TIMEOUT || 2000);\nexport const MAX_CONCURRENT_CREATE_ROOM_WAIT_TIME = Number(process.env.COLYSEUS_MAX_CONCURRENT_CREATE_ROOM_WAIT_TIME || 0.5);\n\nexport function generateId(length: number = 9) {\n return nanoid(length);\n}\n\nexport function getBearerToken(authHeader: string) {\n return (authHeader && authHeader.startsWith(\"Bearer \") && authHeader.substring(7, authHeader.length)) || undefined;\n}\n\n// nodemon sends SIGUSR2 before reloading\n// (https://github.com/remy/nodemon#controlling-shutdown-of-your-script)\n//\nconst signals: NodeJS.Signals[] = ['SIGINT', 'SIGTERM', 'SIGUSR2'];\n\nexport function registerGracefulShutdown(callback: (err?: Error) => void) {\n /**\n * Gracefully shutdown on uncaught errors\n */\n process.on('uncaughtException', (err) => {\n debugAndPrintError(err);\n callback(err);\n });\n\n signals.forEach((signal) =>\n process.once(signal, () => callback()));\n}\n\nexport function retry<T = any>(\n cb: Function,\n maxRetries: number = 3,\n errorWhiteList: any[] = [],\n retries: number = 0,\n) {\n return new Promise<T>((resolve, reject) => {\n cb()\n .then(resolve)\n .catch((e: any) => {\n if (\n errorWhiteList.indexOf(e.constructor) !== -1 &&\n retries++ < maxRetries\n ) {\n setTimeout(() => {\n debugMatchMaking(\"retrying due to error (error: %s, retries: %s, maxRetries: %s)\", e.message, retries, maxRetries);\n retry<T>(cb, maxRetries, errorWhiteList, retries).\n then(resolve).\n catch((e2) => reject(e2));\n }, Math.floor(Math.random() * Math.pow(2, retries) * 400));\n\n } else {\n reject(e);\n }\n });\n });\n}\n\nexport function spliceOne(arr: any[], index: number): boolean {\n // manually splice availableRooms array\n // http://jsperf.com/manual-splice\n if (index === -1 || index >= arr.length) {\n return false;\n }\n\n const len = arr.length - 1;\n for (let i = index; i < len; i++) {\n arr[i] = arr[i + 1];\n }\n\n arr.length = len;\n return true;\n}\n\nexport class Deferred<T = any> {\n public promise: Promise<T>;\n\n public resolve: Function;\n public reject: Function;\n\n constructor(promise?: Promise<T>) {\n this.promise = promise ?? new Promise<T>((resolve, reject) => {\n this.resolve = resolve;\n this.reject = reject;\n });\n }\n\n public then(onFulfilled?: (value: T) => any, onRejected?: (reason: any) => any) {\n return this.promise.then(onFulfilled, onRejected);\n }\n\n public catch(func: (value: any) => any) {\n return this.promise.catch(func);\n }\n\n static reject (reason?: any) {\n return new Deferred(Promise.reject(reason));\n }\n\n static resolve<T = any>(value?: T) {\n return new Deferred<T>(Promise.resolve(value));\n }\n\n}\n\nexport function merge(a: any, ...objs: any[]): any {\n for (let i = 0, len = objs.length; i < len; i++) {\n const b = objs[i];\n for (const key in b) {\n if (b.hasOwnProperty(key)) {\n a[key] = b[key];\n }\n }\n }\n return a;\n}\n\nexport function wrapTryCatch(\n method: Function,\n onError: (error: RoomException, methodName: RoomMethodName) => void,\n exceptionClass: Type<RoomException>,\n methodName: RoomMethodName,\n rethrow: boolean = false,\n ...additionalErrorArgs: any[]\n) {\n return (...args: any[]) => {\n try {\n const result = method(...args);\n if (typeof (result?.catch) === \"function\") {\n return result.catch((e: Error) => {\n onError(new exceptionClass(e, e.message, ...args, ...additionalErrorArgs), methodName);\n if (rethrow) { throw e; }\n });\n }\n return result;\n } catch (e: any) {\n onError(new exceptionClass(e, e.message, ...args, ...additionalErrorArgs), methodName);\n if (rethrow) { throw e; }\n }\n };\n}\n\n/**\n * Dynamically import a module using either require() or import()\n * based on the current module system (CJS vs ESM).\n *\n * This avoids double-loading packages when running in mixed ESM/CJS environments.\n * Errors are silently caught - await the promise and handle errors at usage site.\n */\nexport function dynamicImport<T = any>(moduleName: string): Promise<T> {\n // __dirname exists in CJS but not in ESM\n if (typeof __dirname !== 'undefined') {\n // CJS context - use require()\n try {\n return Promise.resolve(require(moduleName));\n } catch (e: any) {\n // If the error is not a MODULE_NOT_FOUND error, reject with the error.\n return Promise.reject((e.code !== 'MODULE_NOT_FOUND') ? e : undefined);\n }\n } else {\n // ESM context - use import()\n const promise = import(moduleName);\n promise.catch(() => {}); // prevent unhandled rejection warnings\n return promise;\n }\n}"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@colyseus/core",
|
|
3
|
-
"version": "0.17.
|
|
3
|
+
"version": "0.17.28",
|
|
4
4
|
"description": "Multiplayer Framework for Node.js.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"input": "./src/index.ts",
|
|
@@ -52,14 +52,14 @@
|
|
|
52
52
|
"debug": "^4.3.4",
|
|
53
53
|
"nanoid": "^3.3.11",
|
|
54
54
|
"@colyseus/shared-types": "^0.17.5",
|
|
55
|
-
"@colyseus/
|
|
56
|
-
"@colyseus/
|
|
55
|
+
"@colyseus/better-call": "^1.2.1",
|
|
56
|
+
"@colyseus/greeting-banner": "^3.0.8"
|
|
57
57
|
},
|
|
58
58
|
"devDependencies": {
|
|
59
59
|
"@colyseus/schema": "^4.0.7",
|
|
60
60
|
"express": "^5.0.0",
|
|
61
|
-
"@colyseus/tools": "^0.17.16",
|
|
62
61
|
"@colyseus/redis-driver": "^0.17.6",
|
|
62
|
+
"@colyseus/tools": "^0.17.17",
|
|
63
63
|
"@colyseus/redis-presence": "^0.17.6"
|
|
64
64
|
},
|
|
65
65
|
"peerDependencies": {
|
package/src/Server.ts
CHANGED
|
@@ -6,7 +6,7 @@ import * as matchMaker from './MatchMaker.ts';
|
|
|
6
6
|
import { RegisteredHandler } from './matchmaker/RegisteredHandler.ts';
|
|
7
7
|
|
|
8
8
|
import { type OnCreateOptions, Room } from './Room.ts';
|
|
9
|
-
import { Deferred, registerGracefulShutdown, type Type } from './utils/Utils.ts';
|
|
9
|
+
import { Deferred, registerGracefulShutdown, dynamicImport, type Type } from './utils/Utils.ts';
|
|
10
10
|
|
|
11
11
|
import type { Presence } from "./presence/Presence.ts";
|
|
12
12
|
import { LocalPresence } from './presence/LocalPresence.ts';
|
|
@@ -167,7 +167,7 @@ export class Server<
|
|
|
167
167
|
|
|
168
168
|
} else {
|
|
169
169
|
try {
|
|
170
|
-
return (await
|
|
170
|
+
return (await dynamicImport("@colyseus/tools")).listen(this);
|
|
171
171
|
} catch (error) {
|
|
172
172
|
const err = new Error("Please install @colyseus/tools to be able to host on Colyseus Cloud.");
|
|
173
173
|
err.cause = error;
|
|
@@ -347,7 +347,7 @@ export class Server<
|
|
|
347
347
|
|
|
348
348
|
protected async getDefaultTransport(options: any): Promise<Transport> {
|
|
349
349
|
try {
|
|
350
|
-
const module = await
|
|
350
|
+
const module = await dynamicImport('@colyseus/ws-transport');
|
|
351
351
|
const WebSocketTransport = module.WebSocketTransport;
|
|
352
352
|
return new WebSocketTransport(options);
|
|
353
353
|
|
package/src/index.ts
CHANGED
|
@@ -52,7 +52,7 @@ export { SchemaSerializer } from './serializer/SchemaSerializer.ts';
|
|
|
52
52
|
|
|
53
53
|
// Utilities
|
|
54
54
|
export { Clock, Delayed };
|
|
55
|
-
export { generateId, Deferred,
|
|
55
|
+
export { generateId, Deferred, spliceOne, getBearerToken, dynamicImport } from './utils/Utils.ts';
|
|
56
56
|
export { isDevMode } from './utils/DevMode.ts';
|
|
57
57
|
|
|
58
58
|
// IPC
|
package/src/utils/Utils.ts
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
import { nanoid } from 'nanoid';
|
|
2
|
-
|
|
3
|
-
import { EventEmitter } from "events";
|
|
4
2
|
import { type RoomException, type RoomMethodName } from '../errors/RoomExceptions.ts';
|
|
5
3
|
|
|
6
4
|
import { debugAndPrintError, debugMatchMaking } from '../Debug.ts';
|
|
@@ -166,4 +164,27 @@ export function wrapTryCatch(
|
|
|
166
164
|
};
|
|
167
165
|
}
|
|
168
166
|
|
|
169
|
-
|
|
167
|
+
/**
|
|
168
|
+
* Dynamically import a module using either require() or import()
|
|
169
|
+
* based on the current module system (CJS vs ESM).
|
|
170
|
+
*
|
|
171
|
+
* This avoids double-loading packages when running in mixed ESM/CJS environments.
|
|
172
|
+
* Errors are silently caught - await the promise and handle errors at usage site.
|
|
173
|
+
*/
|
|
174
|
+
export function dynamicImport<T = any>(moduleName: string): Promise<T> {
|
|
175
|
+
// __dirname exists in CJS but not in ESM
|
|
176
|
+
if (typeof __dirname !== 'undefined') {
|
|
177
|
+
// CJS context - use require()
|
|
178
|
+
try {
|
|
179
|
+
return Promise.resolve(require(moduleName));
|
|
180
|
+
} catch (e: any) {
|
|
181
|
+
// If the error is not a MODULE_NOT_FOUND error, reject with the error.
|
|
182
|
+
return Promise.reject((e.code !== 'MODULE_NOT_FOUND') ? e : undefined);
|
|
183
|
+
}
|
|
184
|
+
} else {
|
|
185
|
+
// ESM context - use import()
|
|
186
|
+
const promise = import(moduleName);
|
|
187
|
+
promise.catch(() => {}); // prevent unhandled rejection warnings
|
|
188
|
+
return promise;
|
|
189
|
+
}
|
|
190
|
+
}
|