{
  "version": 3,
  "sources": ["../src/index.ts"],
  "sourcesContent": ["import './loadenv.ts';\nimport os from 'os';\nimport fs from \"fs\";\nimport net from \"net\";\nimport http from 'http';\nimport type express from 'express';\nimport {\n  type ServerOptions,\n  type SDKTypes,\n  type Router,\n  logger,\n  Server,\n  Transport,\n  matchMaker,\n  RegisteredHandler,\n  defineServer,\n  dynamicImport,\n} from '@colyseus/core';\nimport { WebSocketTransport } from '@colyseus/ws-transport';\n\nconst BunWebSockets = dynamicImport('@colyseus/bun-websockets');\nconst RedisDriver = dynamicImport('@colyseus/redis-driver');\nconst RedisPresence = dynamicImport('@colyseus/redis-presence');\n\nexport interface ConfigOptions<\n  RoomTypes extends Record<string, RegisteredHandler> = any,\n  Routes extends Router = any\n> extends SDKTypes<RoomTypes, Routes> {\n    options?: ServerOptions,\n    displayLogs?: boolean,\n    rooms?: RoomTypes,\n    routes?: Routes,\n    initializeTransport?: (options: any) => Transport,\n    initializeExpress?: (app: express.Application) => void,\n    initializeGameServer?: (app: Server) => void,\n    beforeListen?: () => void,\n    /**\n     * @deprecated getId() has no effect anymore.\n     */\n    getId?: () => string,\n}\n\nconst ALLOWED_KEYS: { [key in keyof Partial<ConfigOptions>]: string } = {\n  'displayLogs': \"boolean\",\n  'options': \"object\",\n  'rooms': \"object\",\n  'routes': \"object\",\n  'initializeTransport': \"function\",\n  'initializeExpress': \"function\",\n  'initializeGameServer': \"function\",\n  'beforeListen': \"function\",\n  // deprecated options (will be removed in the next major version)\n  'getId': \"function\",\n};\n\nexport default function <\n  RoomTypes extends Record<string, RegisteredHandler> = any,\n  Routes extends Router = any\n>(options: Omit<ConfigOptions<RoomTypes, Routes>, '~rooms' | '~routes'>) {\n  for (const option in options) {\n    if (!ALLOWED_KEYS[option]) {\n      throw new Error(`\u274C Invalid option '${option}'. Allowed options are: ${Object.keys(ALLOWED_KEYS).join(\", \")}`);\n    }\n    if(options[option] !== undefined && typeof(options[option]) !== ALLOWED_KEYS[option]) {\n      throw new Error(`\u274C Invalid type for ${option}: please provide a ${ALLOWED_KEYS[option]} value.`);\n    }\n  }\n  return options as ConfigOptions<RoomTypes, Routes>;\n}\n\n/**\n * Expose server instance and listen on the port specified\n * @param options Application options\n * @param port Port number to bind Colyseus + Express\n */\nexport async function listen<\n  RoomTypes extends Record<string, RegisteredHandler> = any,\n  Routes extends Router = any\n>(\n    options: ConfigOptions<RoomTypes, Routes>,\n    port?: number,\n): Promise<Server<RoomTypes, Routes>>;\n\n/**\n * Expose server instance and listen on the port specified\n * @param server Server instance\n * @param port Port number to bind Colyseus + Express\n */\nexport async function listen<\n  RoomTypes extends Record<string, RegisteredHandler> = any,\n  Routes extends Router = any\n>(\n    server: Server<RoomTypes, Routes>,\n    port?: number,\n): Promise<Server<RoomTypes, Routes>>;\n\nexport async function listen<\n  RoomTypes extends Record<string, RegisteredHandler> = any,\n  Routes extends Router = any\n>(\n    options: ConfigOptions<RoomTypes, Routes> | Server<RoomTypes, Routes>,\n    port: number = Number(process.env.PORT || 2567),\n) {\n    // Force 2567 port on Colyseus Cloud\n    if (process.env.COLYSEUS_CLOUD !== undefined) {\n        port = 2567;\n    }\n\n    //\n    // Handling multiple processes\n    // Use NODE_APP_INSTANCE to play nicely with pm2\n    //\n    const processNumber = Number(process.env.NODE_APP_INSTANCE || \"0\");\n    port += processNumber;\n\n    let server: Server<RoomTypes, Routes>;\n    let displayLogs = true;\n\n    if (options instanceof Server) {\n        server = options;\n\n        // automatically configure for production under Colyseus Cloud\n        // if on Colyseus Cloud, the matchMaker should have been configured by the time we get here\n        // See @colyseus/core src/utils/Env.ts\n\n    } else {\n        server = await buildServerFromOptions<RoomTypes, Routes>(options, port);\n        displayLogs = options.displayLogs;\n\n        await options.initializeGameServer?.(server);\n        await matchMaker.onReady;\n        await options.beforeListen?.();\n    }\n\n    if (process.env.COLYSEUS_CLOUD !== undefined) {\n        // listening on socket\n        const socketPath = `/run/colyseus/${port}.sock`;\n        // const socketPath: any = `/tmp/${port}.sock`;\n\n        // check if .sock file is active\n        // (fixes \"ADDRINUSE\" issue when restarting the server)\n        await checkInactiveSocketFile(socketPath);\n\n        await server.listen(\n          socketPath,\n          0 as any // workaround to allow using @colyseus/core's .listen() directly on Colyseus Cloud\n        );\n\n    } else {\n        // listening on port\n        await server.listen(port);\n    }\n\n    // notify process manager (production)\n    if (typeof(process.send) === \"function\") {\n        process.send('ready');\n    }\n\n    if (displayLogs) {\n        logger.info(`\u2694\uFE0F  Listening on http://localhost:${port}`);\n    }\n\n    return server;\n}\n\nasync function buildServerFromOptions<\n  RoomTypes extends Record<string, RegisteredHandler> = any,\n  Routes extends Router = any\n>(options: ConfigOptions<RoomTypes, Routes>, port: number) {\n  const serverOptions = options.options || {};\n  options.displayLogs = options.displayLogs ?? true;\n\n  // automatically configure for production under Colyseus Cloud\n  if (process.env.COLYSEUS_CLOUD !== undefined) {\n    const cloudConfig = await getColyseusCloudConfig(port, serverOptions.driver, serverOptions.presence);\n    if (cloudConfig) {\n      serverOptions.driver = cloudConfig.driver;\n      serverOptions.presence = cloudConfig.presence;\n      serverOptions.publicAddress = cloudConfig.publicAddress;\n    }\n  }\n\n  return defineServer<RoomTypes, Routes>({\n    rooms: options.rooms || {} as RoomTypes,\n    routes: options.routes,\n    ...serverOptions,\n    express: options.initializeExpress,\n    transport: await getTransport(options),\n  });\n}\n\nexport async function getTransport(options: ConfigOptions) {\n    let transport: Transport;\n\n    if (!options.initializeTransport) {\n        // @ts-ignore\n        if (typeof Bun !== \"undefined\") {\n          // @colyseus/bun-websockets\n          BunWebSockets.catch(() => {\n            logger.warn(\"\");\n            logger.warn(\"\u274C could not initialize BunWebSockets.\");\n            logger.warn(\"\uD83D\uDC49 npm install --save @colyseus/bun-websockets\");\n            logger.warn(\"\");\n          })\n          const module = await BunWebSockets;\n          options.initializeTransport = (options: any) => new module.BunWebSockets(options);\n\n        } else {\n          // use WebSocketTransport by default\n          options.initializeTransport = (options: any) => new WebSocketTransport(options);\n        }\n    }\n\n    // Create server without express app - the transport handles express via getExpressApp()\n    const server = http.createServer();\n\n    transport = await options.initializeTransport({ server });\n\n    return transport;\n}\n\n/**\n * Configure Redis driver/presence for Colyseus Cloud when needed.\n * Returns configured driver, presence, and publicAddress.\n */\nasync function getColyseusCloudConfig(port: number, currentDriver?: any, currentPresence?: any) {\n  const useRedisConfig = (os.cpus().length > 1) || (process.env.REDIS_URI !== undefined);\n\n  if (!useRedisConfig) {\n    return null;\n  }\n\n  let driver = currentDriver;\n  let presence = currentPresence;\n  const publicAddress = process.env.SUBDOMAIN + \".\" + process.env.SERVER_NAME + \"/\" + port;\n\n  if (!driver) {\n    try {\n      const module = await RedisDriver;\n      driver = new module.RedisDriver(process.env.REDIS_URI);\n    } catch (e) {\n      console.error(e);\n      logger.warn(\"\");\n      logger.warn(\"\u274C could not initialize RedisDriver.\");\n      logger.warn(\"\uD83D\uDC49 npm install --save @colyseus/redis-driver\");\n      logger.warn(\"\");\n    }\n  }\n\n  if (!presence) {\n    try {\n      const module = await RedisPresence;\n      presence = new module.RedisPresence(process.env.REDIS_URI);\n    } catch (e) {\n      console.error(e);\n      logger.warn(\"\");\n      logger.warn(\"\u274C could not initialize RedisPresence.\");\n      logger.warn(\"\uD83D\uDC49 npm install --save @colyseus/redis-presence\");\n      logger.warn(\"\");\n    }\n  }\n\n  return { driver, presence, publicAddress };\n}\n\n/**\n * Check if a socket file is active and remove it if it's not.\n */\nfunction checkInactiveSocketFile(sockFilePath: string) {\n  return new Promise((resolve, reject) => {\n    const client = net.createConnection({ path: sockFilePath })\n      .on('connect', () => {\n        // socket file is active, close the connection\n        client.end();\n        throw new Error(`EADDRINUSE: Already listening on '${sockFilePath}'`);\n      })\n      .on('error', () => {\n        // socket file is inactive, remove it\n        fs.unlink(sockFilePath, () => resolve(true));\n      });\n  });\n}\n"],
  "mappings": "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",
  "names": ["options"]
}
