{"version":3,"sources":["jsdelivr-header.js","/npm/partysocket@1.1.19/src/ws.ts","/npm/partysocket@1.1.19/src/index.ts"],"names":[],"mappings":"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","file":"/npm/partysocket@1.1.19/dist/index.js/+esm","sourceRoot":"","sourcesContent":["/**\n * Bundled by jsDelivr using Rollup v2.79.2 and Terser v5.48.0.\n * Original file: /npm/partysocket@1.1.19/dist/index.js\n *\n * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files\n */\n","// TODO: lose this eslint-disable\n\n/*!\n * Reconnecting WebSocket\n * by Pedro Ladaria <pedro.ladaria@gmail.com>\n * https://github.com/pladaria/reconnecting-websocket\n * License MIT\n */\n\nimport type { TypedEventTarget } from \"./type-helper\";\n\nif (!globalThis.EventTarget || !globalThis.Event) {\n  console.error(`\n  PartySocket requires a global 'EventTarget' class to be available!\n  You can polyfill this global by adding this to your code before any partysocket imports: \n  \n  \\`\\`\\`\n  import 'partysocket/event-target-polyfill';\n  \\`\\`\\`\n  Please file an issue at https://github.com/partykit/partykit if you're still having trouble.\n`);\n}\n\nexport class ErrorEvent extends Event {\n  public message: string;\n  public error: Error;\n  // oxlint-disable-next-line no-explicit-any\n  constructor(error: Error, target: any) {\n    super(\"error\", target);\n    this.message = error.message;\n    this.error = error;\n  }\n}\n\nexport class CloseEvent extends Event {\n  public code: number;\n  public reason: string;\n  public wasClean = true;\n  // oxlint-disable-next-line no-explicit-any\n  constructor(code = 1000, reason = \"\", target: any) {\n    super(\"close\", target);\n    this.code = code;\n    this.reason = reason;\n  }\n}\nexport interface WebSocketEventMap {\n  close: CloseEvent;\n  error: ErrorEvent;\n  message: MessageEvent;\n  open: Event;\n}\n\nconst Events = {\n  Event,\n  ErrorEvent,\n  CloseEvent\n};\n\nfunction assert(condition: unknown, msg?: string): asserts condition {\n  if (!condition) {\n    throw new Error(msg);\n  }\n}\n\nfunction cloneEventBrowser(e: Event) {\n  // oxlint-disable-next-line no-explicit-any\n  return new (e as any).constructor(e.type, e) as Event;\n}\n\nfunction cloneEventNode(e: Event) {\n  if (\"data\" in e) {\n    const evt = new MessageEvent(e.type, e);\n    return evt;\n  }\n\n  if (\"code\" in e || \"reason\" in e) {\n    const evt = new CloseEvent(\n      // @ts-expect-error we need to fix event/listener types\n      (e.code || 1999) as number,\n      // @ts-expect-error we need to fix event/listener types\n      (e.reason || \"unknown reason\") as string,\n      e\n    );\n    return evt;\n  }\n\n  if (\"error\" in e) {\n    const evt = new ErrorEvent(e.error as Error, e);\n    return evt;\n  }\n\n  const evt = new Event(e.type, e);\n  return evt;\n}\n\nconst isNode =\n  typeof process !== \"undefined\" &&\n  typeof process.versions?.node !== \"undefined\";\n\n// React Native has process and document polyfilled but not process.versions.node\n// It needs Node-style event cloning because browser-style cloning produces\n// events that fail instanceof Event checks in event-target-polyfill\n// See: https://github.com/cloudflare/partykit/issues/257\nconst isReactNative =\n  typeof navigator !== \"undefined\" && navigator.product === \"ReactNative\";\n\nconst cloneEvent = isNode || isReactNative ? cloneEventNode : cloneEventBrowser;\n\nexport type Options = {\n  // oxlint-disable-next-line no-explicit-any\n  WebSocket?: any;\n  maxReconnectionDelay?: number;\n  minReconnectionDelay?: number;\n  reconnectionDelayGrowFactor?: number;\n  minUptime?: number;\n  connectionTimeout?: number;\n  maxRetries?: number;\n  maxEnqueuedMessages?: number;\n  startClosed?: boolean;\n  debug?: boolean;\n  // oxlint-disable-next-line no-explicit-any\n  debugLogger?: (...args: any[]) => void;\n};\n\nconst DEFAULT = {\n  maxReconnectionDelay: 10000,\n  minReconnectionDelay: 3000,\n  minUptime: 5000,\n  reconnectionDelayGrowFactor: 1.3,\n  connectionTimeout: 4000,\n  maxRetries: Number.POSITIVE_INFINITY,\n  maxEnqueuedMessages: Number.POSITIVE_INFINITY,\n  startClosed: false,\n  debug: false\n};\n\nlet didWarnAboutMissingWebSocket = false;\n\nexport type UrlProvider = string | (() => string) | (() => Promise<string>);\nexport type ProtocolsProvider =\n  | null\n  | string\n  | string[]\n  | (() => string | string[] | null)\n  | (() => Promise<string | string[] | null>);\n\nexport type Message =\n  | string\n  | ArrayBuffer\n  | Blob\n  | ArrayBufferView<ArrayBuffer>;\n\nexport default class ReconnectingWebSocket extends (EventTarget as TypedEventTarget<WebSocketEventMap>) {\n  private _ws: WebSocket | undefined;\n  private _retryCount = -1;\n  private _uptimeTimeout: ReturnType<typeof setTimeout> | undefined;\n  private _connectTimeout: ReturnType<typeof setTimeout> | undefined;\n  private _shouldReconnect = true;\n  private _connectLock = false;\n  private _binaryType: BinaryType = \"blob\";\n  private _closeCalled = false;\n  private _messageQueue: Message[] = [];\n\n  private _debugLogger = console.log.bind(console);\n\n  protected _url: UrlProvider;\n  protected _protocols?: ProtocolsProvider;\n  protected _options: Options;\n\n  constructor(\n    url: UrlProvider,\n    protocols?: ProtocolsProvider,\n    options: Options = {}\n  ) {\n    super();\n    this._url = url;\n    this._protocols = protocols;\n    this._options = options;\n    if (this._options.startClosed) {\n      this._shouldReconnect = false;\n    }\n    if (this._options.debugLogger) {\n      this._debugLogger = this._options.debugLogger;\n    }\n    this._connect();\n  }\n\n  static get CONNECTING() {\n    return 0;\n  }\n  static get OPEN() {\n    return 1;\n  }\n  static get CLOSING() {\n    return 2;\n  }\n  static get CLOSED() {\n    return 3;\n  }\n\n  get CONNECTING() {\n    return ReconnectingWebSocket.CONNECTING;\n  }\n  get OPEN() {\n    return ReconnectingWebSocket.OPEN;\n  }\n  get CLOSING() {\n    return ReconnectingWebSocket.CLOSING;\n  }\n  get CLOSED() {\n    return ReconnectingWebSocket.CLOSED;\n  }\n\n  get binaryType() {\n    return this._ws ? this._ws.binaryType : this._binaryType;\n  }\n\n  set binaryType(value: BinaryType) {\n    this._binaryType = value;\n    if (this._ws) {\n      this._ws.binaryType = value;\n    }\n  }\n\n  /**\n   * Returns the number or connection retries\n   */\n  get retryCount(): number {\n    return Math.max(this._retryCount, 0);\n  }\n\n  /**\n   * The number of bytes of data that have been queued using calls to send() but not yet\n   * transmitted to the network. This value resets to zero once all queued data has been sent.\n   * This value does not reset to zero when the connection is closed; if you keep calling send(),\n   * this will continue to climb. Read only\n   */\n  get bufferedAmount(): number {\n    const bytes = this._messageQueue.reduce((acc, message) => {\n      if (typeof message === \"string\") {\n        acc += message.length; // not byte size\n      } else if (message instanceof Blob) {\n        acc += message.size;\n      } else {\n        acc += message.byteLength;\n      }\n      return acc;\n    }, 0);\n    return bytes + (this._ws ? this._ws.bufferedAmount : 0);\n  }\n\n  /**\n   * The extensions selected by the server. This is currently only the empty string or a list of\n   * extensions as negotiated by the connection\n   */\n  get extensions(): string {\n    return this._ws ? this._ws.extensions : \"\";\n  }\n\n  /**\n   * A string indicating the name of the sub-protocol the server selected;\n   * this will be one of the strings specified in the protocols parameter when creating the\n   * WebSocket object\n   */\n  get protocol(): string {\n    return this._ws ? this._ws.protocol : \"\";\n  }\n\n  /**\n   * The current state of the connection; this is one of the Ready state constants\n   */\n  get readyState(): number {\n    if (this._ws) {\n      return this._ws.readyState;\n    }\n    return this._options.startClosed\n      ? ReconnectingWebSocket.CLOSED\n      : ReconnectingWebSocket.CONNECTING;\n  }\n\n  /**\n   * The URL as resolved by the constructor\n   */\n  get url(): string {\n    return this._ws ? this._ws.url : \"\";\n  }\n\n  /**\n   * Whether the websocket object is now in reconnectable state\n   */\n  get shouldReconnect(): boolean {\n    return this._shouldReconnect;\n  }\n\n  /**\n   * An event listener to be called when the WebSocket connection's readyState changes to CLOSED\n   */\n  public onclose: ((event: CloseEvent) => void) | null = null;\n\n  /**\n   * An event listener to be called when an error occurs\n   */\n  public onerror: ((event: ErrorEvent) => void) | null = null;\n\n  /**\n   * An event listener to be called when a message is received from the server\n   */\n  public onmessage: ((event: MessageEvent) => void) | null = null;\n\n  /**\n   * An event listener to be called when the WebSocket connection's readyState changes to OPEN;\n   * this indicates that the connection is ready to send and receive data\n   */\n  public onopen: ((event: Event) => void) | null = null;\n\n  /**\n   * Closes the WebSocket connection or connection attempt, if any. If the connection is already\n   * CLOSED, this method does nothing\n   */\n  public close(code = 1000, reason?: string) {\n    this._closeCalled = true;\n    this._shouldReconnect = false;\n    this._clearTimeouts();\n    if (!this._ws) {\n      this._debug(\"close enqueued: no ws instance\");\n      return;\n    }\n    if (this._ws.readyState === this.CLOSED) {\n      this._debug(\"close: already closed\");\n      return;\n    }\n    this._ws.close(code, reason);\n  }\n\n  /**\n   * Closes the WebSocket connection or connection attempt and connects again.\n   * Resets retry counter;\n   */\n  public reconnect(code?: number, reason?: string) {\n    this._shouldReconnect = true;\n    this._closeCalled = false;\n    this._retryCount = -1;\n    if (!this._ws || this._ws.readyState === this.CLOSED) {\n      this._connect();\n    } else {\n      this._disconnect(code, reason);\n      this._connect();\n    }\n  }\n\n  /**\n   * Enqueue specified data to be transmitted to the server over the WebSocket connection\n   */\n  public send(data: Message) {\n    if (this._ws && this._ws.readyState === this.OPEN) {\n      this._debug(\"send\", data);\n      this._ws.send(data);\n    } else {\n      const { maxEnqueuedMessages = DEFAULT.maxEnqueuedMessages } =\n        this._options;\n      if (this._messageQueue.length < maxEnqueuedMessages) {\n        this._debug(\"enqueue\", data);\n        this._messageQueue.push(data);\n      }\n    }\n  }\n\n  private _debug(...args: unknown[]) {\n    if (this._options.debug) {\n      this._debugLogger(\"RWS>\", ...args);\n    }\n  }\n\n  private _getNextDelay() {\n    const {\n      reconnectionDelayGrowFactor = DEFAULT.reconnectionDelayGrowFactor,\n      minReconnectionDelay = DEFAULT.minReconnectionDelay,\n      maxReconnectionDelay = DEFAULT.maxReconnectionDelay\n    } = this._options;\n    let delay = 0;\n    if (this._retryCount > 0) {\n      delay =\n        minReconnectionDelay *\n        reconnectionDelayGrowFactor ** (this._retryCount - 1);\n      if (delay > maxReconnectionDelay) {\n        delay = maxReconnectionDelay;\n      }\n    }\n    this._debug(\"next delay\", delay);\n    return delay;\n  }\n\n  private _wait(): Promise<void> {\n    return new Promise((resolve) => {\n      setTimeout(resolve, this._getNextDelay());\n    });\n  }\n\n  private _getNextProtocols(\n    protocolsProvider: ProtocolsProvider | null\n  ): Promise<string | string[] | null> {\n    if (!protocolsProvider) return Promise.resolve(null);\n\n    if (\n      typeof protocolsProvider === \"string\" ||\n      Array.isArray(protocolsProvider)\n    ) {\n      return Promise.resolve(protocolsProvider);\n    }\n\n    if (typeof protocolsProvider === \"function\") {\n      const protocols = protocolsProvider();\n      if (!protocols) return Promise.resolve(null);\n\n      if (typeof protocols === \"string\" || Array.isArray(protocols)) {\n        return Promise.resolve(protocols);\n      }\n\n      // @ts-expect-error redundant check\n      if (protocols.then) {\n        return protocols;\n      }\n    }\n\n    throw Error(\"Invalid protocols\");\n  }\n\n  private _getNextUrl(urlProvider: UrlProvider): Promise<string> {\n    if (typeof urlProvider === \"string\") {\n      return Promise.resolve(urlProvider);\n    }\n    if (typeof urlProvider === \"function\") {\n      const url = urlProvider();\n      if (typeof url === \"string\") {\n        return Promise.resolve(url);\n      }\n      // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n      // @ts-expect-error\n      if (url.then) {\n        return url;\n      }\n\n      // return url;\n    }\n    throw Error(\"Invalid URL\");\n  }\n\n  private _connect() {\n    if (this._connectLock || !this._shouldReconnect) {\n      return;\n    }\n    this._connectLock = true;\n\n    const {\n      maxRetries = DEFAULT.maxRetries,\n      connectionTimeout = DEFAULT.connectionTimeout\n    } = this._options;\n\n    if (this._retryCount >= maxRetries) {\n      this._debug(\"max retries reached\", this._retryCount, \">=\", maxRetries);\n      this._connectLock = false;\n      return;\n    }\n\n    this._retryCount++;\n\n    this._debug(\"connect\", this._retryCount);\n    this._removeListeners();\n\n    this._wait()\n      .then(() =>\n        Promise.all([\n          this._getNextUrl(this._url),\n          this._getNextProtocols(this._protocols || null)\n        ])\n      )\n      .then(([url, protocols]) => {\n        // close could be called before creating the ws\n        if (this._closeCalled) {\n          this._connectLock = false;\n          return;\n        }\n        if (\n          !this._options.WebSocket &&\n          typeof WebSocket === \"undefined\" &&\n          !didWarnAboutMissingWebSocket\n        ) {\n          console.error(`‼️ No WebSocket implementation available. You should define options.WebSocket. \n\nFor example, if you're using node.js, run \\`npm install ws\\`, and then in your code:\n\nimport PartySocket from 'partysocket';\nimport WS from 'ws';\n\nconst partysocket = new PartySocket({\n  host: \"127.0.0.1:1999\",\n  room: \"test-room\",\n  WebSocket: WS\n});\n\n`);\n          didWarnAboutMissingWebSocket = true;\n        }\n        const WS: typeof WebSocket = this._options.WebSocket || WebSocket;\n        this._debug(\"connect\", { url, protocols });\n        this._ws = protocols ? new WS(url, protocols) : new WS(url);\n\n        this._ws.binaryType = this._binaryType;\n        this._connectLock = false;\n        this._addListeners();\n\n        this._connectTimeout = setTimeout(\n          () => this._handleTimeout(),\n          connectionTimeout\n        );\n      })\n      // via https://github.com/pladaria/reconnecting-websocket/pull/166\n      .catch((err) => {\n        this._connectLock = false;\n        this._handleError(new Events.ErrorEvent(Error(err.message), this));\n      });\n  }\n\n  private _handleTimeout() {\n    this._debug(\"timeout event\");\n    this._handleError(new Events.ErrorEvent(Error(\"TIMEOUT\"), this));\n  }\n\n  private _disconnect(code = 1000, reason?: string) {\n    this._clearTimeouts();\n    if (!this._ws) {\n      return;\n    }\n    this._removeListeners();\n    try {\n      if (\n        this._ws.readyState === this.OPEN ||\n        this._ws.readyState === this.CONNECTING\n      ) {\n        this._ws.close(code, reason);\n      }\n      this._handleClose(new Events.CloseEvent(code, reason, this));\n    } catch (_error) {\n      // ignore\n    }\n  }\n\n  private _acceptOpen() {\n    this._debug(\"accept open\");\n    this._retryCount = 0;\n  }\n\n  private _handleOpen = (event: Event) => {\n    this._debug(\"open event\");\n    const { minUptime = DEFAULT.minUptime } = this._options;\n\n    clearTimeout(this._connectTimeout);\n    this._uptimeTimeout = setTimeout(() => this._acceptOpen(), minUptime);\n\n    assert(this._ws, \"WebSocket is not defined\");\n\n    this._ws.binaryType = this._binaryType;\n\n    // send enqueued messages (messages sent before websocket open event)\n    this._messageQueue.forEach((message) => {\n      this._ws?.send(message);\n    });\n    this._messageQueue = [];\n\n    if (this.onopen) {\n      this.onopen(event);\n    }\n    this.dispatchEvent(cloneEvent(event));\n  };\n\n  private _handleMessage = (event: MessageEvent) => {\n    this._debug(\"message event\");\n\n    if (this.onmessage) {\n      this.onmessage(event);\n    }\n    this.dispatchEvent(cloneEvent(event));\n  };\n\n  private _handleError = (event: ErrorEvent) => {\n    this._debug(\"error event\", event.message);\n    this._disconnect(\n      undefined,\n      event.message === \"TIMEOUT\" ? \"timeout\" : undefined\n    );\n\n    if (this.onerror) {\n      this.onerror(event);\n    }\n    this._debug(\"exec error listeners\");\n    this.dispatchEvent(cloneEvent(event));\n\n    this._connect();\n  };\n\n  private _handleClose = (event: CloseEvent) => {\n    this._debug(\"close event\");\n    this._clearTimeouts();\n\n    if (this._shouldReconnect) {\n      this._connect();\n    }\n\n    if (this.onclose) {\n      this.onclose(event);\n    }\n    this.dispatchEvent(cloneEvent(event));\n  };\n\n  private _removeListeners() {\n    if (!this._ws) {\n      return;\n    }\n    this._debug(\"removeListeners\");\n    this._ws.removeEventListener(\"open\", this._handleOpen);\n    this._ws.removeEventListener(\"close\", this._handleClose);\n    this._ws.removeEventListener(\"message\", this._handleMessage);\n    // @ts-expect-error we need to fix event/listerner types\n    this._ws.removeEventListener(\"error\", this._handleError);\n  }\n\n  private _addListeners() {\n    if (!this._ws) {\n      return;\n    }\n    this._debug(\"addListeners\");\n    this._ws.addEventListener(\"open\", this._handleOpen);\n    this._ws.addEventListener(\"close\", this._handleClose);\n    this._ws.addEventListener(\"message\", this._handleMessage);\n    // @ts-expect-error we need to fix event/listener types\n    this._ws.addEventListener(\"error\", this._handleError);\n  }\n\n  private _clearTimeouts() {\n    clearTimeout(this._connectTimeout);\n    clearTimeout(this._uptimeTimeout);\n  }\n}\n","import ReconnectingWebSocket from \"./ws\";\n\nimport type * as RWS from \"./ws\";\nimport type { ProtocolsProvider } from \"./ws\";\n\ntype Maybe<T> = T | null | undefined;\ntype Params = Record<string, Maybe<string>>;\nconst valueIsNotNil = <T>(\n  keyValuePair: [string, Maybe<T>]\n): keyValuePair is [string, T] =>\n  keyValuePair[1] !== null && keyValuePair[1] !== undefined;\n\nexport type PartySocketOptions = Omit<RWS.Options, \"constructor\"> & {\n  id?: string; // the id of the client\n  host: string; // base url for the party\n  room?: string; // the room to connect to\n  party?: string; // the party to connect to (defaults to main)\n  basePath?: string; // the base path to use for the party\n  prefix?: string; // the prefix to use for the party\n  protocol?: \"ws\" | \"wss\";\n  protocols?: ProtocolsProvider;\n  path?: string; // the path to connect to\n  query?: Params | (() => Params | Promise<Params>);\n  disableNameValidation?: boolean; // disable validation of party/room names\n  // headers\n};\n\nexport type PartyFetchOptions = {\n  host: string; // base url for the party\n  room: string; // the room to connect to\n  party?: string; // the party to fetch from (defaults to main)\n  basePath?: string; // the base path to use for the party\n  prefix?: string; // the prefix to use for the party\n  path?: string; // the path to fetch from\n  protocol?: \"http\" | \"https\";\n  query?: Params | (() => Params | Promise<Params>);\n  fetch?: typeof fetch;\n};\n\nfunction generateUUID(): string {\n  // Public Domain/MIT\n  if (crypto?.randomUUID) {\n    return crypto.randomUUID();\n  }\n  let d = Date.now(); //Timestamp\n  let d2 = (performance?.now && performance.now() * 1000) || 0; //Time in microseconds since page-load or 0 if unsupported\n  // oxlint-disable-next-line func-style\n  return \"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\".replace(/[xy]/g, function (c) {\n    let r = Math.random() * 16; //random number between 0 and 16\n    if (d > 0) {\n      //Use timestamp until depleted\n      r = ((d + r) % 16) | 0;\n      d = Math.floor(d / 16);\n    } else {\n      //Use microseconds since page-load if supported\n      r = ((d2 + r) % 16) | 0;\n      d2 = Math.floor(d2 / 16);\n    }\n    return (c === \"x\" ? r : (r & 0x3) | 0x8).toString(16);\n  });\n}\n\nfunction getPartyInfo(\n  partySocketOptions: PartySocketOptions | PartyFetchOptions,\n  defaultProtocol: \"http\" | \"ws\",\n  defaultParams: Record<string, string> = {}\n) {\n  const {\n    host: rawHost,\n    path: rawPath,\n    protocol: rawProtocol,\n    room,\n    party,\n    basePath,\n    prefix,\n    query\n  } = partySocketOptions;\n\n  // strip the protocol from the beginning of `host` if any\n  let host = rawHost.replace(/^(http|https|ws|wss):\\/\\//, \"\");\n  // if user provided a trailing slash, remove it\n  if (host.endsWith(\"/\")) {\n    host = host.slice(0, -1);\n  }\n\n  if (rawPath?.startsWith(\"/\")) {\n    throw new Error(\"path must not start with a slash\");\n  }\n\n  const name = party ?? \"main\";\n  const path = rawPath ? `/${rawPath}` : \"\";\n  const protocol =\n    rawProtocol ||\n    (host.startsWith(\"localhost:\") ||\n    host.startsWith(\"127.0.0.1:\") ||\n    host.startsWith(\"192.168.\") ||\n    host.startsWith(\"10.\") ||\n    (host.startsWith(\"172.\") &&\n      host.split(\".\")[1] >= \"16\" &&\n      host.split(\".\")[1] <= \"31\") ||\n    host.startsWith(\"[::ffff:7f00:1]:\")\n      ? // http / ws\n        defaultProtocol\n      : // https / wss\n        `${defaultProtocol}s`);\n\n  const baseUrl = `${protocol}://${host}/${basePath || `${prefix || \"parties\"}/${name}/${room}`}${path}`;\n\n  const makeUrl = (query: Params = {}) =>\n    `${baseUrl}?${new URLSearchParams([\n      ...Object.entries(defaultParams),\n      ...Object.entries(query).filter(valueIsNotNil)\n    ])}`;\n\n  // allow urls to be defined as functions\n  const urlProvider =\n    typeof query === \"function\"\n      ? async () => makeUrl(await query())\n      : makeUrl(query);\n\n  return {\n    host,\n    path,\n    room,\n    name,\n    protocol,\n    partyUrl: baseUrl,\n    urlProvider\n  };\n}\n\n// things that nathanboktae/robust-websocket claims are better:\n// doesn't do anything in offline mode (?)\n// \"natively aware of error codes\"\n// can do custom reconnect strategies\n\n// TODO: incorporate the above notes\nexport default class PartySocket extends ReconnectingWebSocket {\n  _pk!: string;\n  _pkurl!: string;\n  name!: string;\n  room?: string;\n  host!: string;\n  path!: string;\n  basePath?: string;\n\n  constructor(readonly partySocketOptions: PartySocketOptions) {\n    const wsOptions = getWSOptions(partySocketOptions);\n\n    super(wsOptions.urlProvider, wsOptions.protocols, wsOptions.socketOptions);\n\n    this.setWSProperties(wsOptions);\n\n    if (!partySocketOptions.startClosed && !this.room && !this.basePath) {\n      this.close();\n      throw new Error(\n        \"Either room or basePath must be provided to connect. Use startClosed: true to create a socket and set them via updateProperties before calling reconnect().\"\n      );\n    }\n\n    if (!partySocketOptions.disableNameValidation) {\n      if (partySocketOptions.party?.includes(\"/\")) {\n        console.warn(\n          `PartySocket: party name \"${partySocketOptions.party}\" contains forward slash which may cause routing issues. Consider using a name without forward slashes or set disableNameValidation: true to bypass this warning.`\n        );\n      }\n      if (partySocketOptions.room?.includes(\"/\")) {\n        console.warn(\n          `PartySocket: room name \"${partySocketOptions.room}\" contains forward slash which may cause routing issues. Consider using a name without forward slashes or set disableNameValidation: true to bypass this warning.`\n        );\n      }\n    }\n  }\n\n  public updateProperties(partySocketOptions: Partial<PartySocketOptions>) {\n    const wsOptions = getWSOptions({\n      ...this.partySocketOptions,\n      ...partySocketOptions,\n      host: partySocketOptions.host ?? this.host,\n      room: partySocketOptions.room ?? this.room,\n      path: partySocketOptions.path ?? this.path,\n      basePath: partySocketOptions.basePath ?? this.basePath\n    });\n\n    this._url = wsOptions.urlProvider;\n    this._protocols = wsOptions.protocols;\n    this._options = wsOptions.socketOptions;\n\n    this.setWSProperties(wsOptions);\n  }\n\n  private setWSProperties(wsOptions: ReturnType<typeof getWSOptions>) {\n    const { _pk, _pkurl, name, room, host, path, basePath } = wsOptions;\n\n    this._pk = _pk;\n    this._pkurl = _pkurl;\n    this.name = name;\n    this.room = room;\n    this.host = host;\n    this.path = path;\n    this.basePath = basePath;\n  }\n\n  public reconnect(\n    code?: number | undefined,\n    reason?: string | undefined\n  ): void {\n    if (!this.host) {\n      throw new Error(\n        \"The host must be set before connecting, use `updateProperties` method to set it or pass it to the constructor.\"\n      );\n    }\n    if (!this.room && !this.basePath) {\n      throw new Error(\n        \"The room (or basePath) must be set before connecting, use `updateProperties` method to set it or pass it to the constructor.\"\n      );\n    }\n    super.reconnect(code, reason);\n  }\n\n  get id() {\n    return this._pk;\n  }\n\n  /**\n   * Exposes the static PartyKit room URL without applying query parameters.\n   * To access the currently connected WebSocket url, use PartySocket#url.\n   */\n  get roomUrl(): string {\n    return this._pkurl;\n  }\n\n  // a `fetch` method that uses (almost) the same options as `PartySocket`\n  static async fetch(\n    options: PartyFetchOptions,\n    init?: RequestInit\n  ): Promise<Response> {\n    const party = getPartyInfo(options, \"http\");\n    const url =\n      typeof party.urlProvider === \"string\"\n        ? party.urlProvider\n        : await party.urlProvider();\n    const doFetch = options.fetch ?? fetch;\n    return doFetch(url, init);\n  }\n}\n\nexport { PartySocket };\n\nexport { ReconnectingWebSocket as WebSocket };\n\nfunction getWSOptions(partySocketOptions: PartySocketOptions) {\n  const {\n    id,\n    host: _host,\n    path: _path,\n    party: _party,\n    room: _room,\n    protocol: _protocol,\n    query: _query,\n    protocols,\n    ...socketOptions\n  } = partySocketOptions;\n\n  const _pk = id || generateUUID();\n  const party = getPartyInfo(partySocketOptions, \"ws\", { _pk });\n\n  return {\n    _pk: _pk,\n    _pkurl: party.partyUrl,\n    name: party.name,\n    room: party.room,\n    host: party.host,\n    path: party.path,\n    basePath: partySocketOptions.basePath,\n    protocols: protocols,\n    socketOptions: socketOptions,\n    urlProvider: party.urlProvider\n  };\n}\n"]}