{"version":3,"sources":["../src/y-electric.ts","../src/local-storage-resume-state.ts","../src/utils.ts"],"sourcesContent":["import * as encoding from 'lib0/encoding'\nimport * as decoding from 'lib0/decoding'\nimport * as awarenessProtocol from 'y-protocols/awareness'\nimport { ObservableV2 } from 'lib0/observable'\nimport * as env from 'lib0/environment'\nimport * as Y from 'yjs'\nimport {\n  GetExtensions,\n  isChangeMessage,\n  isControlMessage,\n  Message,\n  Offset,\n  Row,\n  ShapeStream,\n  ShapeStreamOptions,\n} from '@electric-sql/client'\nimport {\n  YProvider,\n  ResumeState,\n  SendErrorRetryHandler,\n  ElectricProviderOptions,\n} from './types'\n\ntype AwarenessUpdate = {\n  added: number[]\n  updated: number[]\n  removed: number[]\n}\n\nexport class ElectricProvider<\n  RowWithDocumentUpdate extends Row<decoding.Decoder> = never,\n  RowWithAwarenessUpdate extends Row<decoding.Decoder> = never,\n> extends ObservableV2<YProvider> {\n  private doc: Y.Doc\n\n  private documentUpdates: {\n    shape: ShapeStreamOptions<GetExtensions<RowWithDocumentUpdate>>\n    sendUrl: string | URL\n    getUpdateFromRow: (row: RowWithDocumentUpdate) => decoding.Decoder\n    sendErrorRetryHandler?: SendErrorRetryHandler\n  }\n\n  private awarenessUpdates?: {\n    shape: ShapeStreamOptions<GetExtensions<RowWithAwarenessUpdate>>\n    sendUrl: string | URL\n    protocol: awarenessProtocol.Awareness\n    getUpdateFromRow: (row: RowWithAwarenessUpdate) => decoding.Decoder\n    sendErrorRetryHandler?: SendErrorRetryHandler\n  }\n\n  private _connected: boolean = false\n  private _synced: boolean = false\n\n  private resumeState: ResumeState\n  private sendingPendingChanges: boolean = false\n  private pendingChanges: Uint8Array | null = null\n  private sendingAwarenessState: boolean = false\n  private pendingAwarenessUpdate: AwarenessUpdate | null = null\n  private debounceMs: number\n  private debounceTimer: ReturnType<typeof setTimeout> | null = null\n\n  private documentUpdateHandler: (\n    update: Uint8Array,\n    origin: unknown,\n    doc: Y.Doc,\n    transaction: Y.Transaction\n  ) => void\n  private awarenessUpdateHandler?: (\n    update: AwarenessUpdate,\n    origin: unknown\n  ) => void\n\n  private exitHandler: () => void\n  private unsubscribeShapes?: () => void\n\n  private fetchClient?: typeof fetch\n\n  /**\n   * Creates a new ElectricProvider instance that connects YJS documents to Electric SQL.\n   *\n   * @constructor\n   * @param {ElectricProviderOptions} options - Configuration options for the provider\n   * @param {Y.Doc} options.doc - The YJS document to be synchronized\n   * @param {Object} options.documentUpdates - Document updates configuration\n   * @param {ShapeStreamOptions} options.documentUpdates.shape - Options for the document updates shape stream\n   * @param {string|URL} options.documentUpdates.sendUrl - URL endpoint for sending document updates\n   * @param {Function} options.documentUpdates.getUpdateFromRow - Function to extract document update from row\n   * @param {SendErrorRetryHandler} [options.documentUpdates.sendErrorRetryHandler] - Error handler for retrying document updates\n   * @param {Object} [options.awarenessUpdates] - Awareness updates configuration (optional)\n   * @param {ShapeStreamOptions} options.awarenessUpdates.shape - Options for the awareness updates shape stream\n   * @param {string|URL} options.awarenessUpdates.sendUrl - URL endpoint for sending awareness updates\n   * @param {awarenessProtocol.Awareness} options.awarenessUpdates.protocol - Awareness protocol instance\n   * @param {Function} options.awarenessUpdates.getUpdateFromRow - Function to extract awareness update from row\n   * @param {SendErrorRetryHandler} [options.awarenessUpdates.sendErrorRetryHandler] - Error handler for retrying awareness updates\n   * @param {ResumeState} [options.resumeState] - Resume state for the provider\n   * @param {boolean} [options.connect=true] - Whether to automatically connect upon initialization\n   * @param {typeof fetch} [options.fetchClient] - Custom fetch implementation to use for HTTP requests\n   * @param {number} [options.debounceMs] - Debounce window in milliseconds for sending document updates. If 0 or undefined, debouncing is disabled.\n   */\n  constructor({\n    doc,\n    documentUpdates: documentUpdatesConfig,\n    awarenessUpdates: awarenessUpdatesConfig,\n    resumeState,\n    connect = true,\n    fetchClient,\n    debounceMs,\n  }: ElectricProviderOptions<RowWithDocumentUpdate, RowWithAwarenessUpdate>) {\n    super()\n\n    this.doc = doc\n    this.documentUpdates = documentUpdatesConfig\n    this.awarenessUpdates = awarenessUpdatesConfig\n    this.resumeState = resumeState ?? {}\n    this.debounceMs = debounceMs ?? 0\n\n    this.fetchClient = fetchClient\n\n    this.exitHandler = () => {\n      if (env.isNode && typeof process !== `undefined`) {\n        process.on(`exit`, this.destroy.bind(this))\n      }\n    }\n\n    this.documentUpdateHandler = this.doc.on(\n      `update`,\n      this.applyDocumentUpdate.bind(this)\n    )\n    if (this.awarenessUpdates) {\n      this.awarenessUpdateHandler = this.applyAwarenessUpdate.bind(this)\n      this.awarenessUpdates.protocol.on(`update`, this.awarenessUpdateHandler!)\n    }\n\n    // enqueue unsynced changes from document if the\n    // resume state provides the document state vector\n    if (this.resumeState?.stableStateVector) {\n      this.pendingChanges = Y.encodeStateAsUpdate(\n        this.doc,\n        this.resumeState.stableStateVector\n      )\n    }\n\n    if (connect) {\n      this.connect()\n    }\n  }\n\n  get synced() {\n    return this._synced\n  }\n\n  set synced(state) {\n    if (this._synced !== state) {\n      this._synced = state\n      this.emit(`synced`, [state])\n      this.emit(`sync`, [state])\n    }\n  }\n\n  set connected(state) {\n    if (this._connected !== state) {\n      this._connected = state\n      if (state) {\n        this.sendOperations()\n      }\n      this.emit(`status`, [{ status: state ? `connected` : `disconnected` }])\n    }\n  }\n\n  get connected() {\n    return this._connected\n  }\n\n  private batch(update: Uint8Array) {\n    if (this.pendingChanges) {\n      this.pendingChanges = Y.mergeUpdates([this.pendingChanges, update])\n    } else {\n      this.pendingChanges = update\n    }\n  }\n\n  private clearDebounceTimer() {\n    if (this.debounceTimer !== null) {\n      clearTimeout(this.debounceTimer)\n      this.debounceTimer = null\n    }\n  }\n\n  private scheduleSendOperations() {\n    if (this.debounceMs > 0) {\n      if (this.debounceTimer === null) {\n        this.debounceTimer = setTimeout(async () => {\n          this.debounceTimer = null\n          await this.sendOperations()\n          if (\n            this.pendingChanges &&\n            this.connected &&\n            !this.sendingPendingChanges\n          ) {\n            this.scheduleSendOperations()\n          }\n        }, this.debounceMs)\n      }\n    } else {\n      this.sendOperations()\n    }\n  }\n\n  destroy() {\n    this.clearDebounceTimer()\n    this.disconnect()\n\n    this.doc.off(`update`, this.documentUpdateHandler)\n    this.awarenessUpdates?.protocol.off(`update`, this.awarenessUpdateHandler!)\n\n    if (env.isNode && typeof process !== `undefined`) {\n      process.off(`exit`, this.exitHandler!)\n    }\n    super.destroy()\n  }\n\n  disconnect() {\n    // Flush any pending changes before disconnecting\n    this.clearDebounceTimer()\n    if (this.pendingChanges && this.connected) {\n      this.sendOperations()\n    }\n\n    this.unsubscribeShapes?.()\n\n    if (!this.connected) {\n      return\n    }\n\n    if (this.awarenessUpdates) {\n      awarenessProtocol.removeAwarenessStates(\n        this.awarenessUpdates.protocol,\n        Array.from(this.awarenessUpdates.protocol.getStates().keys()).filter(\n          (client) => client !== this.awarenessUpdates!.protocol.clientID\n        ),\n        this\n      )\n\n      // try to notifying other clients that we are disconnecting\n      awarenessProtocol.removeAwarenessStates(\n        this.awarenessUpdates.protocol,\n        [this.awarenessUpdates.protocol.clientID],\n        `local`\n      )\n\n      this.awarenessUpdates.protocol.setLocalState({})\n    }\n\n    // TODO: await for events before closing\n    this.emit(`connection-close`, [])\n\n    this.pendingAwarenessUpdate = null\n\n    this.connected = false\n    this.synced = false\n  }\n\n  connect() {\n    if (this.connected) {\n      return\n    }\n    const abortController = new AbortController()\n\n    const operationsStream = new ShapeStream<RowWithDocumentUpdate>({\n      ...this.documentUpdates.shape,\n      ...this.resumeState.document,\n      signal: abortController.signal,\n    })\n\n    const operationsShapeUnsubscribe = operationsStream.subscribe(\n      (messages: Message<RowWithDocumentUpdate>[]) => {\n        this.operationsShapeHandler(\n          messages,\n          operationsStream.lastOffset,\n          operationsStream.shapeHandle!\n        )\n      }\n    )\n\n    let awarenessShapeUnsubscribe: () => void | undefined\n    if (this.awarenessUpdates) {\n      const awarenessStream = new ShapeStream<RowWithAwarenessUpdate>({\n        ...this.awarenessUpdates.shape,\n        signal: abortController.signal,\n        offset: `now`,\n      })\n\n      awarenessShapeUnsubscribe = awarenessStream.subscribe(\n        (messages: Message<RowWithAwarenessUpdate>[]) => {\n          this.awarenessShapeHandler(messages)\n        }\n      )\n    }\n\n    this.unsubscribeShapes = () => {\n      abortController.abort()\n      operationsShapeUnsubscribe()\n      awarenessShapeUnsubscribe?.()\n      this.unsubscribeShapes = undefined\n    }\n\n    this.emit(`status`, [{ status: `connecting` }])\n  }\n\n  private operationsShapeHandler(\n    messages: Message<RowWithDocumentUpdate>[],\n    offset: Offset,\n    handle: string\n  ) {\n    for (const message of messages) {\n      if (isChangeMessage(message)) {\n        const decoder = this.documentUpdates.getUpdateFromRow(message.value)\n        while (decoder.pos !== decoder.arr.length) {\n          const operation = decoding.readVarUint8Array(decoder)\n          Y.applyUpdate(this.doc, operation, `server`)\n        }\n      } else if (\n        isControlMessage(message) &&\n        message.headers.control === `up-to-date`\n      ) {\n        this.resumeState.document = {\n          offset,\n          handle,\n        }\n\n        if (!this.sendingPendingChanges) {\n          this.synced = true\n          this.resumeState.stableStateVector = Y.encodeStateVector(this.doc)\n        }\n        this.emit(`resumeState`, [this.resumeState])\n        this.connected = true\n      }\n    }\n  }\n\n  private async applyDocumentUpdate(update: Uint8Array, origin: unknown) {\n    // don't re-send updates from electric\n    if (origin === `server`) {\n      return\n    }\n\n    this.batch(update)\n    this.scheduleSendOperations()\n  }\n\n  private async sendOperations() {\n    this.clearDebounceTimer()\n\n    if (!this.connected || this.sendingPendingChanges) {\n      return\n    }\n\n    try {\n      this.sendingPendingChanges = true\n      while (\n        this.pendingChanges &&\n        this.pendingChanges.length > 2 &&\n        this.connected\n      ) {\n        const sending = this.pendingChanges\n        this.pendingChanges = null\n\n        const encoder = encoding.createEncoder()\n        encoding.writeVarUint8Array(encoder, sending)\n\n        const success = await send(\n          encoder,\n          this.documentUpdates.sendUrl,\n          this.fetchClient ?? fetch,\n          this.documentUpdates.sendErrorRetryHandler\n        )\n        if (!success) {\n          this.batch(sending)\n          this.disconnect()\n        }\n      }\n      // no more pending changes, move stableStateVector forward\n      this.resumeState.stableStateVector = Y.encodeStateVector(this.doc)\n      this.emit(`resumeState`, [this.resumeState])\n    } finally {\n      this.sendingPendingChanges = false\n    }\n  }\n\n  private async applyAwarenessUpdate(\n    awarenessUpdate: AwarenessUpdate,\n    origin: unknown\n  ) {\n    if (origin !== `local` || !this.connected) {\n      return\n    }\n\n    this.pendingAwarenessUpdate = awarenessUpdate\n\n    if (this.sendingAwarenessState) {\n      return\n    }\n\n    this.sendingAwarenessState = true\n\n    try {\n      while (this.pendingAwarenessUpdate && this.connected) {\n        const update = this.pendingAwarenessUpdate\n        this.pendingAwarenessUpdate = null\n\n        const { added, updated, removed } = update\n        const changedClients = added.concat(updated).concat(removed)\n        const encoder = encoding.createEncoder()\n\n        encoding.writeVarUint8Array(\n          encoder,\n          awarenessProtocol.encodeAwarenessUpdate(\n            this.awarenessUpdates!.protocol,\n            changedClients\n          )\n        )\n        const success = await send(\n          encoder,\n          this.awarenessUpdates!.sendUrl,\n          this.fetchClient ?? fetch,\n          this.awarenessUpdates!.sendErrorRetryHandler\n        )\n        if (!success) {\n          this.disconnect()\n        }\n      }\n    } finally {\n      this.sendingAwarenessState = false\n    }\n  }\n\n  private awarenessShapeHandler(messages: Message<RowWithAwarenessUpdate>[]) {\n    for (const message of messages) {\n      if (isChangeMessage(message)) {\n        if (message.headers.operation === `delete`) {\n          awarenessProtocol.removeAwarenessStates(\n            this.awarenessUpdates!.protocol,\n            [Number(message.value.client_id)],\n            `remote`\n          )\n        } else {\n          const decoder = this.awarenessUpdates!.getUpdateFromRow(message.value)\n          awarenessProtocol.applyAwarenessUpdate(\n            this.awarenessUpdates!.protocol,\n            decoding.readVarUint8Array(decoder),\n            this\n          )\n        }\n      }\n    }\n  }\n}\n\nasync function send(\n  encoder: encoding.Encoder,\n  endpoint: string | URL,\n  fetchClient: typeof fetch,\n  retryHandler?: SendErrorRetryHandler\n): Promise<boolean> {\n  let response: Response | undefined\n  const op = encoding.toUint8Array(encoder)\n\n  try {\n    response = await fetchClient(endpoint!, {\n      method: `PUT`,\n      headers: {\n        'Content-Type': `application/octet-stream`,\n      },\n      body: op as BodyInit,\n    })\n\n    if (!response.ok) {\n      throw new Error(`Server did not return 2xx`)\n    }\n\n    return true\n  } catch (error) {\n    const shouldRetry = await (retryHandler?.({\n      response,\n      error,\n    }) ?? false)\n    return shouldRetry\n  }\n}\n","import { ResumeState, ElectricResumeStateProvider } from './types'\nimport { ObservableV2 } from 'lib0/observable.js'\nimport { ElectricProvider } from './y-electric'\nimport * as buffer from 'lib0/buffer'\n\n/**\n * A ResumeStateProvider implementation using LocalStorage.\n * This is a reference implementation that can be used as a starting point\n * for implementing other ResumeStateProviders.\n */\nexport class LocalStorageResumeStateProvider extends ObservableV2<ElectricResumeStateProvider> {\n  private key: string\n  private resumeState?: ResumeState\n\n  constructor(key: string) {\n    super()\n    this.key = key\n  }\n\n  subscribeToResumeState(provider: ElectricProvider): () => void {\n    const resumeStateHandler = provider.on(`resumeState`, this.save.bind(this))\n    return () => provider.off(`resumeState`, resumeStateHandler)\n  }\n\n  save(resumeState: ResumeState) {\n    const jsonPart = JSON.stringify({\n      operations: resumeState.document,\n    })\n    localStorage.setItem(this.key, jsonPart)\n\n    if (resumeState.stableStateVector) {\n      const vectorBase64 = buffer.toBase64(resumeState.stableStateVector)\n      localStorage.setItem(`${this.key}_vector`, vectorBase64)\n    } else {\n      // ensure vector is removed\n      localStorage.removeItem(`${this.key}_vector`)\n    }\n  }\n\n  load(): ResumeState {\n    if (this.resumeState) {\n      return this.resumeState\n    }\n\n    const jsonData = localStorage.getItem(this.key)\n    if (!jsonData) {\n      this.emit(`synced`, [{}])\n    } else {\n      this.resumeState = JSON.parse(jsonData)\n\n      const vectorData = localStorage.getItem(`${this.key}_vector`)\n      if (vectorData) {\n        this.resumeState!.stableStateVector = buffer.fromBase64(vectorData)\n      }\n\n      this.emit(`synced`, [this.resumeState!])\n    }\n\n    return this.resumeState!\n  }\n}\n","import * as decoding from 'lib0/decoding'\n\n/**\n * Convert a hex string from PostgreSQL's bytea format to a Uint8Array\n */\nconst hexStringToUint8Array = (hexString: string) => {\n  const cleanHexString = hexString.startsWith(`\\\\x`)\n    ? hexString.slice(2)\n    : hexString\n  return new Uint8Array(\n    cleanHexString.match(/.{1,2}/g)!.map((byte) => parseInt(byte, 16))\n  )\n}\n\n/**\n * Utility to parse hex string bytea data to a decoder for YJS operations\n */\nexport const parseToDecoder = {\n  bytea: (hexString: string) => {\n    const uint8Array = hexStringToUint8Array(hexString)\n    return decoding.createDecoder(uint8Array)\n  },\n}\n"],"mappings":"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","names":["encoding","decoding","awarenessProtocol","ObservableV2","env","Y","isChangeMessage","isControlMessage","ShapeStream","ElectricProvider","ObservableV2","doc","documentUpdatesConfig","awarenessUpdatesConfig","resumeState","connect","fetchClient","debounceMs","_a","state","update","client","abortController","operationsStream","ShapeStream","__spreadProps","__spreadValues","operationsShapeUnsubscribe","messages","awarenessShapeUnsubscribe","offset","handle","message","isChangeMessage","decoder","operation","isControlMessage","origin","sending","encoder","send","awarenessUpdate","added","updated","removed","changedClients","endpoint","retryHandler","response","op","error","ObservableV2","buffer","LocalStorageResumeStateProvider","key","provider","resumeStateHandler","resumeState","jsonPart","vectorBase64","jsonData","vectorData","decoding","hexStringToUint8Array","hexString","cleanHexString","byte","parseToDecoder","uint8Array"]}