{"version":3,"file":"connection.mjs","names":[],"sources":["../../../src/mixins/ratelimiters/connection.ts"],"sourcesContent":["import { Sema } from \"async-sema\";\n\nimport type { ClientMixin, ConnectionMixin } from \"../base-mixin\";\nimport type { ChatClient } from \"~/client/client\";\nimport type { SingleConnection } from \"~/client/connection\";\nimport { applyReplacements } from \"~/utils/apply-function-replacements\";\n\nexport interface ConnectionRateLimits {\n  parallelConnections: number;\n  releaseTime: number;\n}\n\nexport class ConnectionRateLimiter implements ClientMixin, ConnectionMixin {\n  private readonly client: ChatClient;\n  private readonly semaphore: Sema;\n\n  public constructor(client: ChatClient) {\n    this.client = client;\n\n    this.semaphore = new Sema(\n      this.client.configuration.connectionRateLimits.parallelConnections,\n    );\n  }\n\n  public async acquire(): Promise<void> {\n    await this.semaphore.acquire();\n  }\n\n  public releaseOnConnect(conn: SingleConnection): void {\n    const unsubscribers: (() => void)[] = [];\n\n    const unsubscribe = (): void => {\n      for (const callback of unsubscribers) callback();\n    };\n\n    const done = (): void => {\n      unsubscribe();\n      setTimeout(\n        () => this.semaphore.release(),\n        this.client.configuration.connectionRateLimits.releaseTime,\n      );\n    };\n\n    conn.on(\"connect\", done);\n    conn.on(\"close\", done);\n\n    unsubscribers.push(\n      () => conn.removeListener(\"connect\", done),\n      () => conn.removeListener(\"close\", done),\n    );\n  }\n\n  public applyToClient(client: ChatClient): void {\n    client.connectionMixins.push(this);\n  }\n\n  public applyToConnection(connection: SingleConnection): void {\n    // override transport.connect\n    applyReplacements(this, connection.transport, {\n      connect(\n        originalFunction: (callback?: () => void) => void,\n        connectionListener?: () => void,\n      ): void {\n        void this.acquire().then(() => {\n          originalFunction(connectionListener);\n          this.releaseOnConnect(connection);\n        });\n      },\n    });\n  }\n}\n"],"mappings":";;;AAYA,IAAa,wBAAb,MAA2E;CACzE;CACA;CAEA,YAAmB,QAAoB;AACrC,OAAK,SAAS;AAEd,OAAK,YAAY,IAAI,KACnB,KAAK,OAAO,cAAc,qBAAqB,oBAChD;;CAGH,MAAa,UAAyB;AACpC,QAAM,KAAK,UAAU,SAAS;;CAGhC,iBAAwB,MAA8B;EACpD,MAAM,gBAAgC,EAAE;EAExC,MAAM,oBAA0B;AAC9B,QAAK,MAAM,YAAY,cAAe,WAAU;;EAGlD,MAAM,aAAmB;AACvB,gBAAa;AACb,oBACQ,KAAK,UAAU,SAAS,EAC9B,KAAK,OAAO,cAAc,qBAAqB,YAChD;;AAGH,OAAK,GAAG,WAAW,KAAK;AACxB,OAAK,GAAG,SAAS,KAAK;AAEtB,gBAAc,WACN,KAAK,eAAe,WAAW,KAAK,QACpC,KAAK,eAAe,SAAS,KAAK,CACzC;;CAGH,cAAqB,QAA0B;AAC7C,SAAO,iBAAiB,KAAK,KAAK;;CAGpC,kBAAyB,YAAoC;AAE3D,oBAAkB,MAAM,WAAW,WAAW,EAC5C,QACE,kBACA,oBACM;AACD,QAAK,SAAS,CAAC,WAAW;AAC7B,qBAAiB,mBAAmB;AACpC,SAAK,iBAAiB,WAAW;KACjC;KAEL,CAAC"}