{
  "version": 3,
  "sources": ["../../src/matchmaker/RegisteredHandler.ts"],
  "sourcesContent": ["import { EventEmitter } from 'events';\nimport { logger } from '../Logger.ts';\nimport { Room } from './../Room.ts';\nimport { updateLobby } from './Lobby.ts';\n\nimport type { IRoomCache, SortOptions, IRoomCacheFilterByKeys, IRoomCacheSortByKeys, ExtractRoomCacheMetadata } from './driver.ts';\nimport type { Client } from '../Transport.ts';\nimport type { Type } from \"../utils/Utils.ts\";\n\nexport const INVALID_OPTION_KEYS: Array<keyof IRoomCache> = [\n  'clients',\n  'locked',\n  'private',\n  // 'maxClients', - maxClients can be useful as filter options\n  'metadata',\n  'name',\n  'processId',\n  'roomId',\n];\n\n/**\n * Type for filterBy that supports both onCreate options and metadata fields\n */\ntype FilterByKeys<RoomType extends Room> =\n  | IRoomCacheFilterByKeys\n  | (ExtractRoomCacheMetadata<RoomType> extends object\n      ? keyof ExtractRoomCacheMetadata<RoomType> & string\n      : never)\n\n/**\n * Type for sortBy that supports room cache fields and metadata fields\n */\ntype SortByKeys<RoomType extends Room> =\n  | IRoomCacheSortByKeys\n  | (ExtractRoomCacheMetadata<RoomType> extends object\n      ? keyof ExtractRoomCacheMetadata<RoomType> & string\n      : never);\n\nexport interface RegisteredHandlerEvents<RoomType extends Room = any> {\n  create: [room: RoomType];\n  lock: [room: RoomType];\n  unlock: [room: RoomType];\n  join: [room: RoomType, client: Client];\n  leave: [room: RoomType, client: Client, willDispose: boolean];\n  dispose: [room: RoomType];\n  'visibility-change': [room: RoomType, isVisible: boolean];\n  'metadata-change': [room: RoomType];\n}\n\nexport class RegisteredHandler<\n  RoomType extends Room = any\n> extends EventEmitter<RegisteredHandlerEvents<RoomType>> {\n  '~room': RoomType;\n\n  public klass: Type<RoomType>;\n  public options: any;\n\n  public name: string;\n  public filterOptions: Array<FilterByKeys<RoomType>> = [];\n  public sortOptions?: SortOptions;\n\n  public realtimeListingEnabled: boolean = false;\n\n  constructor(klass: Type<RoomType>, options?: any) {\n    super();\n\n    this.klass = klass;\n    this.options = options;\n\n    if (typeof(klass) !== 'function') {\n      logger.debug('You are likely not importing your room class correctly.');\n      throw new Error(`class is expected but ${typeof(klass)} was provided.`);\n    }\n  }\n\n  public enableRealtimeListing() {\n    this.realtimeListingEnabled = true;\n    this.on('create', (room) => updateLobby(room));\n    this.on('lock', (room) => updateLobby(room));\n    this.on('unlock', (room) => updateLobby(room));\n    this.on('join', (room) => updateLobby(room));\n    this.on('leave', (room, _, willDispose) => {\n      if (!willDispose) {\n        updateLobby(room);\n      }\n    });\n    this.on('visibility-change', (room, isVisible) => updateLobby(room, isVisible));\n    this.on('metadata-change', (room) => updateLobby(room));\n    this.on('dispose', (room) => updateLobby(room, true));\n    return this;\n  }\n\n  /**\n   * Define which fields should be used for filtering rooms.\n   * Supports both onCreate options and metadata fields using dot notation.\n   *\n   * @example\n   * // Filter by IRoomCache fields\n   * .filterBy(['maxClients'])\n   *\n   * @example\n   * // Filter by metadata fields\n   * .filterBy(['difficulty', 'metadata.region'])\n   *\n   * @example\n   * // Mix both\n   * .filterBy(['mode', 'difficulty', 'maxClients'])\n   */\n  public filterBy<T extends FilterByKeys<RoomType>>(\n    options: T[]\n  ) {\n    this.filterOptions = options;\n    return this;\n  }\n\n  /**\n   * Define how rooms should be sorted when querying.\n   * Supports both room cache fields and metadata fields using dot notation.\n   *\n   * @example\n   * // Sort by number of clients (descending)\n   * .sortBy({ clients: -1 })\n   *\n   * @example\n   * // Sort by metadata field\n   * .sortBy({ 'metadata.rating': -1 })\n   *\n   * @example\n   * // Multiple sort criteria\n   * .sortBy({ 'metadata.skillLevel': 1, clients: -1 })\n   */\n  public sortBy<T extends SortByKeys<RoomType>>(\n    options: { [K in T]: SortOptions[string] }\n  ): this {\n    this.sortOptions = options as unknown as SortOptions;\n    return this;\n  }\n\n  public getMetadataFromOptions(options: any) {\n    const metadata = this.getFilterOptions(options);\n\n    if (this.sortOptions) {\n      for (const field in this.sortOptions) {\n        if (field in options && !(field in metadata)) {\n          metadata[field] = options[field];\n        }\n      }\n    }\n\n    return Object.keys(metadata).length > 0 ? { metadata } : {};\n  }\n\n  /**\n   * Extract filter options from client options.\n   */\n  public getFilterOptions(options: any) {\n    return this.filterOptions.reduce((prev, curr, i, arr) => {\n      const field = String(arr[i]);\n\n      // Handle regular (non-metadata) fields\n      if (options.hasOwnProperty(field)) {\n        if (INVALID_OPTION_KEYS.indexOf(field as any) !== -1) {\n          logger.warn(`option \"${field}\" has internal usage and is going to be ignored.`);\n        } else {\n          prev[field] = options[field];\n        }\n      }\n\n      return prev;\n    }, {});\n  }\n}\n"],
  "mappings": ";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oBAA6B;AAC7B,oBAAuB;AACvB,kBAAqB;AACrB,mBAA4B;AAMrB,IAAM,sBAA+C;AAAA,EAC1D;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AA+BO,IAAM,oBAAN,cAEG,2BAAgD;AAAA,EAYxD,YAAY,OAAuB,SAAe;AAChD,UAAM;AANR,SAAO,gBAA+C,CAAC;AAGvD,SAAO,yBAAkC;AAKvC,SAAK,QAAQ;AACb,SAAK,UAAU;AAEf,QAAI,OAAO,UAAW,YAAY;AAChC,2BAAO,MAAM,yDAAyD;AACtE,YAAM,IAAI,MAAM,yBAAyB,OAAO,KAAM,gBAAgB;AAAA,IACxE;AAAA,EACF;AAAA,EAEO,wBAAwB;AAC7B,SAAK,yBAAyB;AAC9B,SAAK,GAAG,UAAU,CAAC,aAAS,0BAAY,IAAI,CAAC;AAC7C,SAAK,GAAG,QAAQ,CAAC,aAAS,0BAAY,IAAI,CAAC;AAC3C,SAAK,GAAG,UAAU,CAAC,aAAS,0BAAY,IAAI,CAAC;AAC7C,SAAK,GAAG,QAAQ,CAAC,aAAS,0BAAY,IAAI,CAAC;AAC3C,SAAK,GAAG,SAAS,CAAC,MAAM,GAAG,gBAAgB;AACzC,UAAI,CAAC,aAAa;AAChB,sCAAY,IAAI;AAAA,MAClB;AAAA,IACF,CAAC;AACD,SAAK,GAAG,qBAAqB,CAAC,MAAM,kBAAc,0BAAY,MAAM,SAAS,CAAC;AAC9E,SAAK,GAAG,mBAAmB,CAAC,aAAS,0BAAY,IAAI,CAAC;AACtD,SAAK,GAAG,WAAW,CAAC,aAAS,0BAAY,MAAM,IAAI,CAAC;AACpD,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAkBO,SACL,SACA;AACA,SAAK,gBAAgB;AACrB,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAkBO,OACL,SACM;AACN,SAAK,cAAc;AACnB,WAAO;AAAA,EACT;AAAA,EAEO,uBAAuB,SAAc;AAC1C,UAAM,WAAW,KAAK,iBAAiB,OAAO;AAE9C,QAAI,KAAK,aAAa;AACpB,iBAAW,SAAS,KAAK,aAAa;AACpC,YAAI,SAAS,WAAW,EAAE,SAAS,WAAW;AAC5C,mBAAS,KAAK,IAAI,QAAQ,KAAK;AAAA,QACjC;AAAA,MACF;AAAA,IACF;AAEA,WAAO,OAAO,KAAK,QAAQ,EAAE,SAAS,IAAI,EAAE,SAAS,IAAI,CAAC;AAAA,EAC5D;AAAA;AAAA;AAAA;AAAA,EAKO,iBAAiB,SAAc;AACpC,WAAO,KAAK,cAAc,OAAO,CAAC,MAAM,MAAM,GAAG,QAAQ;AACvD,YAAM,QAAQ,OAAO,IAAI,CAAC,CAAC;AAG3B,UAAI,QAAQ,eAAe,KAAK,GAAG;AACjC,YAAI,oBAAoB,QAAQ,KAAY,MAAM,IAAI;AACpD,+BAAO,KAAK,WAAW,KAAK,kDAAkD;AAAA,QAChF,OAAO;AACL,eAAK,KAAK,IAAI,QAAQ,KAAK;AAAA,QAC7B;AAAA,MACF;AAEA,aAAO;AAAA,IACT,GAAG,CAAC,CAAC;AAAA,EACP;AACF;",
  "names": []
}
