{"version":3,"file":"index.cjs","names":["YDoc","awarenessProtocol","decoding","syncProtocol","UndoManager","XmlText","XmlElement","XmlFragment","encoding","Server"],"sources":["../../src/server/index.ts"],"sourcesContent":["import * as decoding from \"lib0/decoding\";\nimport * as encoding from \"lib0/encoding\";\nimport debounce from \"lodash.debounce\";\nimport type { Connection, ConnectionContext, WSMessage } from \"partyserver\";\nimport { Server } from \"partyserver\";\nimport * as awarenessProtocol from \"y-protocols/awareness\";\nimport * as syncProtocol from \"y-protocols/sync\";\nimport {\n  applyUpdate,\n  Doc as YDoc,\n  encodeStateAsUpdate,\n  encodeStateVector,\n  UndoManager,\n  XmlText,\n  XmlElement,\n  XmlFragment\n} from \"yjs\";\n\nconst snapshotOrigin = Symbol(\"snapshot-origin\");\ntype YjsRootType =\n  | \"Text\"\n  | \"Map\"\n  | \"Array\"\n  | \"XmlText\"\n  | \"XmlElement\"\n  | \"XmlFragment\";\n\nconst wsReadyStateConnecting = 0;\nconst wsReadyStateOpen = 1;\n// oxlint-disable-next-line no-unused-vars\nconst wsReadyStateClosing = 2;\n// oxlint-disable-next-line no-unused-vars\nconst wsReadyStateClosed = 3;\n\nconst messageSync = 0;\nconst messageAwareness = 1;\n// oxlint-disable-next-line no-unused-vars\nconst messageAuth = 2;\n\n/**\n * Internal key used in connection.setState() to track which awareness\n * client IDs are controlled by each connection. This survives hibernation\n * because connection state is persisted to WebSocket attachments.\n */\nconst AWARENESS_IDS_KEY = \"__ypsAwarenessIds\";\n\ntype YServerConnectionState = {\n  [AWARENESS_IDS_KEY]?: number[];\n  [key: string]: unknown;\n};\n\nfunction getAwarenessIds(conn: Connection): number[] {\n  try {\n    const state = conn.state as YServerConnectionState | null;\n    return state?.[AWARENESS_IDS_KEY] ?? [];\n  } catch {\n    return [];\n  }\n}\n\nfunction setAwarenessIds(conn: Connection, ids: number[]): void {\n  try {\n    conn.setState((prev: YServerConnectionState | null) => ({\n      ...prev,\n      [AWARENESS_IDS_KEY]: ids\n    }));\n  } catch {\n    // ignore — may fail if connection is already closed\n  }\n}\n\nclass WSSharedDoc extends YDoc {\n  awareness: awarenessProtocol.Awareness;\n\n  constructor() {\n    super({ gc: true });\n    this.awareness = new awarenessProtocol.Awareness(this);\n    this.awareness.setLocalState(null);\n\n    // Disable the awareness protocol's built-in check interval.\n    // It renews the local clock every 15s and removes peers after 30s,\n    // but we handle peer cleanup via onClose instead. Clearing it here\n    // prevents it from defeating Durable Object hibernation.\n    clearInterval(\n      (\n        this.awareness as unknown as {\n          _checkInterval: ReturnType<typeof setInterval>;\n        }\n      )._checkInterval\n    );\n  }\n}\n\nconst CALLBACK_DEFAULTS = {\n  debounceWait: 2000,\n  debounceMaxWait: 10000,\n  timeout: 5000\n};\n\nfunction readSyncMessage(\n  decoder: decoding.Decoder,\n  encoder: encoding.Encoder,\n  doc: YDoc,\n  transactionOrigin: Connection,\n  readOnly = false\n) {\n  const messageType = decoding.readVarUint(decoder);\n  switch (messageType) {\n    case syncProtocol.messageYjsSyncStep1:\n      syncProtocol.readSyncStep1(decoder, encoder, doc);\n      break;\n    case syncProtocol.messageYjsSyncStep2:\n      if (!readOnly)\n        syncProtocol.readSyncStep2(decoder, doc, transactionOrigin);\n      break;\n    case syncProtocol.messageYjsUpdate:\n      if (!readOnly) syncProtocol.readUpdate(decoder, doc, transactionOrigin);\n      break;\n    default:\n      throw new Error(\"Unknown message type\");\n  }\n  return messageType;\n}\n\nfunction send(conn: Connection, m: Uint8Array): void {\n  if (\n    conn.readyState !== undefined &&\n    conn.readyState !== wsReadyStateConnecting &&\n    conn.readyState !== wsReadyStateOpen\n  ) {\n    return;\n  }\n  try {\n    conn.send(m);\n  } catch {\n    // connection is broken, ignore\n  }\n}\n\nexport interface CallbackOptions {\n  debounceWait?: number;\n  debounceMaxWait?: number;\n  timeout?: number;\n}\n\ntype ServerClass = new (...args: any[]) => Server;\n\nexport interface YjsInstance {\n  readonly document: WSSharedDoc;\n  onLoad(): Promise<YDoc | void>;\n  onSave(): Promise<void>;\n  unstable_replaceDocument(\n    snapshotUpdate: Uint8Array,\n    getMetadata?: (key: string) => YjsRootType\n  ): void;\n  isReadOnly(connection: Connection): boolean;\n  onCustomMessage(connection: Connection, message: string): void;\n  sendCustomMessage(connection: Connection, message: string): void;\n  broadcastCustomMessage(message: string, excludeConnection?: Connection): void;\n  handleMessage(connection: Connection, message: WSMessage): void;\n}\n\nexport interface YjsStatic {\n  callbackOptions: CallbackOptions;\n}\n\nexport function withYjs<TBase extends ServerClass>(\n  Base: TBase\n): TBase & YjsStatic & (new (...args: any[]) => YjsInstance) {\n  class YjsMixin extends Base {\n    static callbackOptions: CallbackOptions = {};\n\n    readonly document: WSSharedDoc = new WSSharedDoc();\n\n    async onLoad(): Promise<YDoc | void> {\n      // to be implemented by the user\n      return;\n    }\n\n    async onSave(): Promise<void> {\n      // to be implemented by the user\n    }\n\n    /**\n     * Replaces the document with a different state using Yjs UndoManager key remapping.\n     *\n     * @param snapshotUpdate - The snapshot update to replace the document with.\n     * @param getMetadata (optional) - A function that returns the type of the root for a given key.\n     */\n    unstable_replaceDocument(\n      snapshotUpdate: Uint8Array,\n      getMetadata: (key: string) => YjsRootType = () => \"Map\"\n    ): void {\n      try {\n        const doc = this.document;\n        const snapshotDoc = new YDoc();\n        applyUpdate(snapshotDoc, snapshotUpdate, snapshotOrigin);\n\n        const currentStateVector = encodeStateVector(doc);\n        const snapshotStateVector = encodeStateVector(snapshotDoc);\n\n        const changesSinceSnapshotUpdate = encodeStateAsUpdate(\n          doc,\n          snapshotStateVector\n        );\n\n        const undoManager = new UndoManager(\n          [...snapshotDoc.share.keys()].map((key) => {\n            const type = getMetadata(key);\n            if (type === \"Text\") {\n              return snapshotDoc.getText(key);\n            } else if (type === \"Map\") {\n              return snapshotDoc.getMap(key);\n            } else if (type === \"Array\") {\n              return snapshotDoc.getArray(key);\n            } else if (type === \"XmlText\") {\n              return snapshotDoc.get(key, XmlText);\n            } else if (type === \"XmlElement\") {\n              return snapshotDoc.get(key, XmlElement);\n            } else if (type === \"XmlFragment\") {\n              return snapshotDoc.get(key, XmlFragment);\n            }\n            throw new Error(`Unknown root type: ${type} for key: ${key}`);\n          }),\n          {\n            trackedOrigins: new Set([snapshotOrigin])\n          }\n        );\n\n        applyUpdate(snapshotDoc, changesSinceSnapshotUpdate, snapshotOrigin);\n        undoManager.undo();\n\n        const documentChangesSinceSnapshotUpdate = encodeStateAsUpdate(\n          snapshotDoc,\n          currentStateVector\n        );\n\n        applyUpdate(this.document, documentChangesSinceSnapshotUpdate);\n      } catch (error) {\n        throw new Error(\n          `Failed to replace document: ${error instanceof Error ? error.message : \"Unknown error\"}`\n        );\n      }\n    }\n\n    async onStart(): Promise<void> {\n      const src = await this.onLoad();\n      if (src != null) {\n        const state = encodeStateAsUpdate(src);\n        applyUpdate(this.document, state);\n      }\n\n      // Broadcast doc updates to all connections.\n      // Uses this.getConnections() which works for both hibernate and non-hibernate\n      // modes and survives DO hibernation (unlike an in-memory Map).\n      this.document.on(\"update\", (update: Uint8Array) => {\n        const encoder = encoding.createEncoder();\n        encoding.writeVarUint(encoder, messageSync);\n        syncProtocol.writeUpdate(encoder, update);\n        const message = encoding.toUint8Array(encoder);\n        for (const conn of this.getConnections()) {\n          send(conn, message);\n        }\n      });\n\n      // Track which awareness clientIDs each connection controls.\n      // Stored in connection.setState() so it survives hibernation.\n      // When conn is null (internal changes like removeAwarenessStates on close),\n      // broadcast the update to remaining connections.\n      // When conn is non-null (client message), handleMessage broadcasts directly.\n      this.document.awareness.on(\n        \"update\",\n        (\n          {\n            added,\n            updated,\n            removed\n          }: {\n            added: Array<number>;\n            updated: Array<number>;\n            removed: Array<number>;\n          },\n          conn: Connection | null\n        ) => {\n          if (conn !== null) {\n            // Track which clientIDs this connection controls\n            try {\n              const currentIds = new Set(getAwarenessIds(conn));\n              for (const clientID of added) currentIds.add(clientID);\n              for (const clientID of removed) currentIds.delete(clientID);\n              setAwarenessIds(conn, [...currentIds]);\n            } catch (_e) {\n              // ignore — best-effort tracking\n            }\n          } else {\n            // Internal awareness change (e.g. removeAwarenessStates on close)\n            // — broadcast to all remaining connections\n            const changedClients = added.concat(updated, removed);\n            const encoder = encoding.createEncoder();\n            encoding.writeVarUint(encoder, messageAwareness);\n            encoding.writeVarUint8Array(\n              encoder,\n              awarenessProtocol.encodeAwarenessUpdate(\n                this.document.awareness,\n                changedClients\n              )\n            );\n            const buff = encoding.toUint8Array(encoder);\n            for (const c of this.getConnections()) {\n              send(c, buff);\n            }\n          }\n        }\n      );\n\n      // Debounced persistence handler\n      const ctor = this.constructor as typeof YjsMixin;\n      this.document.on(\n        \"update\",\n        debounce(\n          (_update: Uint8Array, _origin: Connection, _doc: YDoc) => {\n            try {\n              this.onSave().catch((err) => {\n                console.error(\"failed to persist:\", err);\n              });\n            } catch (err) {\n              console.error(\"failed to persist:\", err);\n            }\n          },\n          ctor.callbackOptions.debounceWait || CALLBACK_DEFAULTS.debounceWait,\n          {\n            maxWait:\n              ctor.callbackOptions.debounceMaxWait ||\n              CALLBACK_DEFAULTS.debounceMaxWait\n          }\n        )\n      );\n\n      // After hibernation wake-up, the doc is empty but existing connections\n      // survive. Re-sync by sending sync step 1 to all connections — they'll\n      // respond with sync step 2 containing their full state.\n      // On first start there are no connections, so this is a no-op.\n      const syncEncoder = encoding.createEncoder();\n      encoding.writeVarUint(syncEncoder, messageSync);\n      syncProtocol.writeSyncStep1(syncEncoder, this.document);\n      const syncMessage = encoding.toUint8Array(syncEncoder);\n      for (const conn of this.getConnections()) {\n        send(conn, syncMessage);\n      }\n    }\n\n    // oxlint-disable-next-line no-unused-vars\n    isReadOnly(connection: Connection): boolean {\n      // to be implemented by the user\n      return false;\n    }\n\n    /**\n     * Handle custom string messages from the client.\n     * Override this method to implement custom message handling.\n     * @param connection - The connection that sent the message\n     * @param message - The custom message string (without the __YPS: prefix)\n     */\n    // oxlint-disable-next-line no-unused-vars\n    onCustomMessage(connection: Connection, message: string): void {\n      // to be implemented by the user\n      console.warn(\n        `Received custom message but onCustomMessage is not implemented in ${this.constructor.name}:`,\n        message\n      );\n    }\n\n    /**\n     * Send a custom string message to a specific connection.\n     * @param connection - The connection to send the message to\n     * @param message - The custom message string to send\n     */\n    sendCustomMessage(connection: Connection, message: string): void {\n      if (\n        connection.readyState !== undefined &&\n        connection.readyState !== wsReadyStateConnecting &&\n        connection.readyState !== wsReadyStateOpen\n      ) {\n        return;\n      }\n      try {\n        connection.send(`__YPS:${message}`);\n      } catch (e) {\n        console.warn(\"Failed to send custom message\", e);\n      }\n    }\n\n    /**\n     * Broadcast a custom string message to all connected clients.\n     * @param message - The custom message string to broadcast\n     * @param excludeConnection - Optional connection to exclude from the broadcast\n     */\n    broadcastCustomMessage(\n      message: string,\n      excludeConnection?: Connection\n    ): void {\n      const formattedMessage = `__YPS:${message}`;\n      for (const conn of this.getConnections()) {\n        if (excludeConnection && conn === excludeConnection) {\n          continue;\n        }\n        if (\n          conn.readyState !== undefined &&\n          conn.readyState !== wsReadyStateConnecting &&\n          conn.readyState !== wsReadyStateOpen\n        ) {\n          continue;\n        }\n        try {\n          conn.send(formattedMessage);\n        } catch (e) {\n          console.warn(\"Failed to broadcast custom message\", e);\n        }\n      }\n    }\n\n    handleMessage(connection: Connection, message: WSMessage) {\n      if (typeof message === \"string\") {\n        // Handle custom messages with __YPS: prefix\n        if (message.startsWith(\"__YPS:\")) {\n          const customMessage = message.slice(6); // Remove __YPS: prefix\n          this.onCustomMessage(connection, customMessage);\n          return;\n        }\n        console.warn(\n          `Received non-prefixed string message. Custom messages should be sent using sendMessage() on the provider.`\n        );\n        return;\n      }\n      try {\n        const encoder = encoding.createEncoder();\n        // Convert ArrayBuffer to Uint8Array if needed (ArrayBufferView like Uint8Array can be used directly)\n        const uint8Array =\n          message instanceof Uint8Array\n            ? message\n            : message instanceof ArrayBuffer\n              ? new Uint8Array(message)\n              : new Uint8Array(\n                  message.buffer,\n                  message.byteOffset,\n                  message.byteLength\n                );\n        const decoder = decoding.createDecoder(uint8Array);\n        const messageType = decoding.readVarUint(decoder);\n        switch (messageType) {\n          case messageSync:\n            encoding.writeVarUint(encoder, messageSync);\n            readSyncMessage(\n              decoder,\n              encoder,\n              this.document,\n              connection,\n              this.isReadOnly(connection)\n            );\n\n            // If the `encoder` only contains the type of reply message and no\n            // message, there is no need to send the message. When `encoder` only\n            // contains the type of reply, its length is 1.\n            if (encoding.length(encoder) > 1) {\n              send(connection, encoding.toUint8Array(encoder));\n            }\n            break;\n          case messageAwareness: {\n            const awarenessData = decoding.readVarUint8Array(decoder);\n            awarenessProtocol.applyAwarenessUpdate(\n              this.document.awareness,\n              awarenessData,\n              connection\n            );\n            // Forward raw awareness bytes to all connections\n            const awarenessEncoder = encoding.createEncoder();\n            encoding.writeVarUint(awarenessEncoder, messageAwareness);\n            encoding.writeVarUint8Array(awarenessEncoder, awarenessData);\n            const awarenessBuff = encoding.toUint8Array(awarenessEncoder);\n            for (const c of this.getConnections()) {\n              send(c, awarenessBuff);\n            }\n            break;\n          }\n        }\n      } catch (err) {\n        console.error(err);\n        // @ts-expect-error - TODO: fix this\n        this.document.emit(\"error\", [err]);\n      }\n    }\n\n    onMessage(conn: Connection, message: WSMessage) {\n      this.handleMessage(conn, message);\n    }\n\n    onClose(\n      connection: Connection<unknown>,\n      _code: number,\n      _reason: string,\n      _wasClean: boolean\n    ): void | Promise<void> {\n      // Read controlled awareness clientIDs from connection state\n      // (survives hibernation unlike an in-memory Map)\n      const controlledIds = getAwarenessIds(connection);\n      if (controlledIds.length > 0) {\n        awarenessProtocol.removeAwarenessStates(\n          this.document.awareness,\n          controlledIds,\n          null\n        );\n      }\n    }\n\n    // TODO: explore why onError gets triggered when a connection closes\n\n    onConnect(\n      conn: Connection<unknown>,\n      _ctx: ConnectionContext\n    ): void | Promise<void> {\n      // Note: awareness IDs are lazily initialized when the first awareness\n      // message is received — no need to call setAwarenessIds(conn, []) here\n\n      // send sync step 1\n      const encoder = encoding.createEncoder();\n      encoding.writeVarUint(encoder, messageSync);\n      syncProtocol.writeSyncStep1(encoder, this.document);\n      send(conn, encoding.toUint8Array(encoder));\n      const awarenessStates = this.document.awareness.getStates();\n      if (awarenessStates.size > 0) {\n        const encoder = encoding.createEncoder();\n        encoding.writeVarUint(encoder, messageAwareness);\n        encoding.writeVarUint8Array(\n          encoder,\n          awarenessProtocol.encodeAwarenessUpdate(\n            this.document.awareness,\n            Array.from(awarenessStates.keys())\n          )\n        );\n        send(conn, encoding.toUint8Array(encoder));\n      }\n    }\n  }\n\n  return YjsMixin as unknown as TBase &\n    YjsStatic &\n    (new (...args: any[]) => YjsInstance);\n}\n\nexport const YServer = withYjs(Server);\n"],"mappings":"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"}