{"version":3,"sources":["../../src/index.ts","../../src/error.ts","../../src/parser.ts","../../src/helpers.ts","../../src/constants.ts","../../src/fetch.ts","../../src/client.ts","../../src/shape.ts"],"sourcesContent":["export * from './client'\nexport * from './shape'\nexport * from './types'\nexport { isChangeMessage, isControlMessage } from './helpers'\nexport { FetchError } from './error'\nexport { type BackoffOptions, BackoffDefaults } from './fetch'\n","export class FetchError extends Error {\n  status: number\n  text?: string\n  json?: object\n  headers: Record<string, string>\n\n  constructor(\n    status: number,\n    text: string | undefined,\n    json: object | undefined,\n    headers: Record<string, string>,\n    public url: string,\n    message?: string\n  ) {\n    super(\n      message ||\n        `HTTP Error ${status} at ${url}: ${text ?? JSON.stringify(json)}`\n    )\n    this.name = `FetchError`\n    this.status = status\n    this.text = text\n    this.json = json\n    this.headers = headers\n  }\n\n  static async fromResponse(\n    response: Response,\n    url: string\n  ): Promise<FetchError> {\n    const status = response.status\n    const headers = Object.fromEntries([...response.headers.entries()])\n    let text: string | undefined = undefined\n    let json: object | undefined = undefined\n\n    const contentType = response.headers.get(`content-type`)\n    if (!response.bodyUsed) {\n      if (contentType && contentType.includes(`application/json`)) {\n        json = (await response.json()) as object\n      } else {\n        text = await response.text()\n      }\n    }\n\n    return new FetchError(status, text, json, headers, url)\n  }\n}\n\nexport class FetchBackoffAbortError extends Error {\n  constructor() {\n    super(`Fetch with backoff aborted`)\n    this.name = `FetchBackoffAbortError`\n  }\n}\n\nexport class InvalidShapeOptionsError extends Error {\n  constructor(message: string) {\n    super(message)\n    this.name = `InvalidShapeOptionsError`\n  }\n}\n\nexport class MissingShapeUrlError extends Error {\n  constructor() {\n    super(`Invalid shape options: missing required url parameter`)\n    this.name = `MissingShapeUrlError`\n  }\n}\n\nexport class InvalidSignalError extends Error {\n  constructor() {\n    super(`Invalid signal option. It must be an instance of AbortSignal.`)\n    this.name = `InvalidSignalError`\n  }\n}\n\nexport class MissingShapeHandleError extends Error {\n  constructor() {\n    super(\n      `shapeHandle is required if this isn't an initial fetch (i.e. offset > -1)`\n    )\n    this.name = `MissingShapeHandleError`\n  }\n}\n\nexport class ReservedParamError extends Error {\n  constructor(reservedParams: string[]) {\n    super(\n      `Cannot use reserved Electric parameter names in custom params: ${reservedParams.join(`, `)}`\n    )\n    this.name = `ReservedParamError`\n  }\n}\n\nexport class ParserNullValueError extends Error {\n  constructor(columnName: string) {\n    super(`Column \"${columnName ?? `unknown`}\" does not allow NULL values`)\n    this.name = `ParserNullValueError`\n  }\n}\n\nexport class ShapeStreamAlreadyRunningError extends Error {\n  constructor() {\n    super(`ShapeStream is already running`)\n    this.name = `ShapeStreamAlreadyRunningError`\n  }\n}\n\nexport class MissingHeadersError extends Error {\n  constructor(url: string, missingHeaders: Array<string>) {\n    let msg = `The response for the shape request to ${url} didn't include the following required headers:\\n`\n    missingHeaders.forEach((h) => {\n      msg += `- ${h}\\n`\n    })\n    msg += `\\nThis is often due to a proxy not setting CORS correctly so that all Electric headers can be read by the client.`\n    msg += `\\nFor more information visit the troubleshooting guide: /docs/guides/troubleshooting/missing-headers`\n    super(msg)\n  }\n}\n","import { ColumnInfo, GetExtensions, Row, Schema, Value } from './types'\nimport { ParserNullValueError } from './error'\n\ntype Token = string\ntype NullableToken = Token | null\nexport type ParseFunction<Extensions = never> = (\n  value: Token,\n  additionalInfo?: Omit<ColumnInfo, `type` | `dims`>\n) => Value<Extensions>\ntype NullableParseFunction<Extensions = never> = (\n  value: NullableToken,\n  additionalInfo?: Omit<ColumnInfo, `type` | `dims`>\n) => Value<Extensions>\n/**\n * @typeParam Extensions - Additional types that can be parsed by this parser beyond the standard SQL types.\n *                         Defaults to no additional types.\n */\nexport type Parser<Extensions = never> = {\n  [key: string]: ParseFunction<Extensions>\n}\n\nconst parseNumber = (value: string) => Number(value)\nconst parseBool = (value: string) => value === `true` || value === `t`\nconst parseBigInt = (value: string) => BigInt(value)\nconst parseJson = (value: string) => JSON.parse(value)\nconst identityParser: ParseFunction = (v: string) => v\n\nexport const defaultParser: Parser = {\n  int2: parseNumber,\n  int4: parseNumber,\n  int8: parseBigInt,\n  bool: parseBool,\n  float4: parseNumber,\n  float8: parseNumber,\n  json: parseJson,\n  jsonb: parseJson,\n}\n\n// Taken from: https://github.com/electric-sql/pglite/blob/main/packages/pglite/src/types.ts#L233-L279\nexport function pgArrayParser<Extensions>(\n  value: Token,\n  parser?: NullableParseFunction<Extensions>\n): Value<Extensions> {\n  let i = 0\n  let char = null\n  let str = ``\n  let quoted = false\n  let last = 0\n  let p: string | undefined = undefined\n\n  function extractValue(x: Token, start: number, end: number) {\n    let val: Token | null = x.slice(start, end)\n    val = val === `NULL` ? null : val\n    return parser ? parser(val) : val\n  }\n\n  function loop(x: string): Array<Value<Extensions>> {\n    const xs = []\n    for (; i < x.length; i++) {\n      char = x[i]\n      if (quoted) {\n        if (char === `\\\\`) {\n          str += x[++i]\n        } else if (char === `\"`) {\n          xs.push(parser ? parser(str) : str)\n          str = ``\n          quoted = x[i + 1] === `\"`\n          last = i + 2\n        } else {\n          str += char\n        }\n      } else if (char === `\"`) {\n        quoted = true\n      } else if (char === `{`) {\n        last = ++i\n        xs.push(loop(x))\n      } else if (char === `}`) {\n        quoted = false\n        last < i && xs.push(extractValue(x, last, i))\n        last = i + 1\n        break\n      } else if (char === `,` && p !== `}` && p !== `\"`) {\n        xs.push(extractValue(x, last, i))\n        last = i + 1\n      }\n      p = char\n    }\n    last < i && xs.push(xs.push(extractValue(x, last, i + 1)))\n    return xs\n  }\n\n  return loop(value)[0]\n}\n\nexport class MessageParser<T extends Row<unknown>> {\n  private parser: Parser<GetExtensions<T>>\n  constructor(parser?: Parser<GetExtensions<T>>) {\n    // Merge the provided parser with the default parser\n    // to use the provided parser whenever defined\n    // and otherwise fall back to the default parser\n    this.parser = { ...defaultParser, ...parser }\n  }\n\n  parse<Result>(messages: string, schema: Schema): Result {\n    return JSON.parse(messages, (key, value) => {\n      // typeof value === `object` && value !== null\n      // is needed because there could be a column named `value`\n      // and the value associated to that column will be a string or null.\n      // But `typeof null === 'object'` so we need to make an explicit check.\n      // We also parse the `old_value`, which appears on updates when `replica=full`.\n      if (\n        (key === `value` || key === `old_value`) &&\n        typeof value === `object` &&\n        value !== null\n      ) {\n        // Parse the row values\n        const row = value as Record<string, Value<GetExtensions<T>>>\n        Object.keys(row).forEach((key) => {\n          row[key] = this.parseRow(key, row[key] as NullableToken, schema)\n        })\n      }\n      return value\n    }) as Result\n  }\n\n  // Parses the message values using the provided parser based on the schema information\n  private parseRow(\n    key: string,\n    value: NullableToken,\n    schema: Schema\n  ): Value<GetExtensions<T>> {\n    const columnInfo = schema[key]\n    if (!columnInfo) {\n      // We don't have information about the value\n      // so we just return it\n      return value\n    }\n\n    // Copy the object but don't include `dimensions` and `type`\n    const { type: typ, dims: dimensions, ...additionalInfo } = columnInfo\n\n    // Pick the right parser for the type\n    // and support parsing null values if needed\n    // if no parser is provided for the given type, just return the value as is\n    const typeParser = this.parser[typ] ?? identityParser\n    const parser = makeNullableParser(typeParser, columnInfo, key)\n\n    if (dimensions && dimensions > 0) {\n      // It's an array\n      const nullablePgArrayParser = makeNullableParser(\n        (value, _) => pgArrayParser(value, parser),\n        columnInfo,\n        key\n      )\n      return nullablePgArrayParser(value)\n    }\n\n    return parser(value, additionalInfo)\n  }\n}\n\nfunction makeNullableParser<Extensions>(\n  parser: ParseFunction<Extensions>,\n  columnInfo: ColumnInfo,\n  columnName?: string\n): NullableParseFunction<Extensions> {\n  const isNullable = !(columnInfo.not_null ?? false)\n  // The sync service contains `null` value for a column whose value is NULL\n  // but if the column value is an array that contains a NULL value\n  // then it will be included in the array string as `NULL`, e.g.: `\"{1,NULL,3}\"`\n  return (value: NullableToken) => {\n    if (value === null) {\n      if (!isNullable) {\n        throw new ParserNullValueError(columnName ?? `unknown`)\n      }\n      return null\n    }\n    return parser(value, columnInfo)\n  }\n}\n","import { ChangeMessage, ControlMessage, Message, Offset, Row } from './types'\n\n/**\n * Type guard for checking {@link Message} is {@link ChangeMessage}.\n *\n * See [TS docs](https://www.typescriptlang.org/docs/handbook/advanced-types.html#user-defined-type-guards)\n * for information on how to use type guards.\n *\n * @param message - the message to check\n * @returns true if the message is a {@link ChangeMessage}\n *\n * @example\n * ```ts\n * if (isChangeMessage(message)) {\n *   const msgChng: ChangeMessage = message // Ok\n *   const msgCtrl: ControlMessage = message // Err, type mismatch\n * }\n * ```\n */\nexport function isChangeMessage<T extends Row<unknown> = Row>(\n  message: Message<T>\n): message is ChangeMessage<T> {\n  return `key` in message\n}\n\n/**\n * Type guard for checking {@link Message} is {@link ControlMessage}.\n *\n * See [TS docs](https://www.typescriptlang.org/docs/handbook/advanced-types.html#user-defined-type-guards)\n * for information on how to use type guards.\n *\n * @param message - the message to check\n * @returns true if the message is a {@link ControlMessage}\n *\n *  * @example\n * ```ts\n * if (isControlMessage(message)) {\n *   const msgChng: ChangeMessage = message // Err, type mismatch\n *   const msgCtrl: ControlMessage = message // Ok\n * }\n * ```\n */\nexport function isControlMessage<T extends Row<unknown> = Row>(\n  message: Message<T>\n): message is ControlMessage {\n  return !isChangeMessage(message)\n}\n\nexport function isUpToDateMessage<T extends Row<unknown> = Row>(\n  message: Message<T>\n): message is ControlMessage & { up_to_date: true } {\n  return isControlMessage(message) && message.headers.control === `up-to-date`\n}\n\n/**\n * Parses the LSN from the up-to-date message and turns it into an offset.\n * The LSN is only present in the up-to-date control message when in SSE mode.\n * If we are not in SSE mode this function will return undefined.\n */\nexport function getOffset(message: ControlMessage): Offset | undefined {\n  const lsn = message.headers.global_last_seen_lsn\n  if (!lsn) {\n    return\n  }\n  return `${lsn}_0` as Offset\n}\n","export const LIVE_CACHE_BUSTER_HEADER = `electric-cursor`\nexport const SHAPE_HANDLE_HEADER = `electric-handle`\nexport const CHUNK_LAST_OFFSET_HEADER = `electric-offset`\nexport const SHAPE_SCHEMA_HEADER = `electric-schema`\nexport const CHUNK_UP_TO_DATE_HEADER = `electric-up-to-date`\nexport const COLUMNS_QUERY_PARAM = `columns`\nexport const LIVE_CACHE_BUSTER_QUERY_PARAM = `cursor`\nexport const SHAPE_HANDLE_QUERY_PARAM = `handle`\nexport const LIVE_QUERY_PARAM = `live`\nexport const OFFSET_QUERY_PARAM = `offset`\nexport const TABLE_QUERY_PARAM = `table`\nexport const WHERE_QUERY_PARAM = `where`\nexport const REPLICA_PARAM = `replica`\nexport const WHERE_PARAMS_PARAM = `params`\nexport const EXPERIMENTAL_LIVE_SSE_QUERY_PARAM = `experimental_live_sse`\nexport const FORCE_DISCONNECT_AND_REFRESH = `force-disconnect-and-refresh`\nexport const PAUSE_STREAM = `pause-stream`\n","import {\n  CHUNK_LAST_OFFSET_HEADER,\n  CHUNK_UP_TO_DATE_HEADER,\n  LIVE_QUERY_PARAM,\n  OFFSET_QUERY_PARAM,\n  SHAPE_HANDLE_HEADER,\n  SHAPE_HANDLE_QUERY_PARAM,\n} from './constants'\nimport {\n  FetchError,\n  FetchBackoffAbortError,\n  MissingHeadersError,\n} from './error'\n\n// Some specific 4xx and 5xx HTTP status codes that we definitely\n// want to retry\nconst HTTP_RETRY_STATUS_CODES = [429]\n\nexport interface BackoffOptions {\n  /**\n   * Initial delay before retrying in milliseconds\n   */\n  initialDelay: number\n  /**\n   * Maximum retry delay in milliseconds\n   */\n  maxDelay: number\n  multiplier: number\n  onFailedAttempt?: () => void\n  debug?: boolean\n}\n\nexport const BackoffDefaults = {\n  initialDelay: 100,\n  maxDelay: 10_000,\n  multiplier: 1.3,\n}\n\nexport function createFetchWithBackoff(\n  fetchClient: typeof fetch,\n  backoffOptions: BackoffOptions = BackoffDefaults\n): typeof fetch {\n  const {\n    initialDelay,\n    maxDelay,\n    multiplier,\n    debug = false,\n    onFailedAttempt,\n  } = backoffOptions\n  return async (...args: Parameters<typeof fetch>): Promise<Response> => {\n    const url = args[0]\n    const options = args[1]\n\n    let delay = initialDelay\n    let attempt = 0\n\n    /* eslint-disable no-constant-condition -- we re-fetch the shape log\n     * continuously until we get a non-ok response. For recoverable errors,\n     * we retry the fetch with exponential backoff. Users can pass in an\n     * AbortController to abort the fetching an any point.\n     * */\n    while (true) {\n      /* eslint-enable no-constant-condition */\n      try {\n        const result = await fetchClient(...args)\n        if (result.ok) return result\n\n        const err = await FetchError.fromResponse(result, url.toString())\n\n        throw err\n      } catch (e) {\n        onFailedAttempt?.()\n        if (options?.signal?.aborted) {\n          throw new FetchBackoffAbortError()\n        } else if (\n          e instanceof FetchError &&\n          !HTTP_RETRY_STATUS_CODES.includes(e.status) &&\n          e.status >= 400 &&\n          e.status < 500\n        ) {\n          // Any client errors cannot be backed off on, leave it to the caller to handle.\n          throw e\n        } else {\n          // Exponentially backoff on errors.\n          // Wait for the current delay duration\n          await new Promise((resolve) => setTimeout(resolve, delay))\n\n          // Increase the delay for the next attempt\n          delay = Math.min(delay * multiplier, maxDelay)\n\n          if (debug) {\n            attempt++\n            console.log(`Retry attempt #${attempt} after ${delay}ms`)\n          }\n        }\n      }\n    }\n  }\n}\n\nconst NO_BODY_STATUS_CODES = [201, 204, 205]\n\n// Ensure body can actually be read in its entirety\nexport function createFetchWithConsumedMessages(fetchClient: typeof fetch) {\n  return async (...args: Parameters<typeof fetch>): Promise<Response> => {\n    const url = args[0]\n    const res = await fetchClient(...args)\n    try {\n      if (res.status < 200 || NO_BODY_STATUS_CODES.includes(res.status)) {\n        return res\n      }\n\n      const text = await res.text()\n      return new Response(text, res)\n    } catch (err) {\n      throw new FetchError(\n        res.status,\n        undefined,\n        undefined,\n        Object.fromEntries([...res.headers.entries()]),\n        url.toString(),\n        err instanceof Error\n          ? err.message\n          : typeof err === `string`\n            ? err\n            : `failed to read body`\n      )\n    }\n  }\n}\n\ninterface ChunkPrefetchOptions {\n  maxChunksToPrefetch: number\n}\n\nconst ChunkPrefetchDefaults = {\n  maxChunksToPrefetch: 2,\n}\n\n/**\n * Creates a fetch client that prefetches subsequent log chunks for\n * consumption by the shape stream without waiting for the chunk bodies\n * themselves to be loaded.\n *\n * @param fetchClient the client to wrap\n * @param prefetchOptions options to configure prefetching\n * @returns wrapped client with prefetch capabilities\n */\nexport function createFetchWithChunkBuffer(\n  fetchClient: typeof fetch,\n  prefetchOptions: ChunkPrefetchOptions = ChunkPrefetchDefaults\n): typeof fetch {\n  const { maxChunksToPrefetch } = prefetchOptions\n\n  let prefetchQueue: PrefetchQueue\n\n  const prefetchClient = async (...args: Parameters<typeof fetchClient>) => {\n    const url = args[0].toString()\n\n    // try to consume from the prefetch queue first, and if request is\n    // not present abort the prefetch queue as it must no longer be valid\n    const prefetchedRequest = prefetchQueue?.consume(...args)\n    if (prefetchedRequest) {\n      return prefetchedRequest\n    }\n\n    prefetchQueue?.abort()\n\n    // perform request and fire off prefetch queue if request is eligible\n    const response = await fetchClient(...args)\n    const nextUrl = getNextChunkUrl(url, response)\n    if (nextUrl) {\n      prefetchQueue = new PrefetchQueue({\n        fetchClient,\n        maxPrefetchedRequests: maxChunksToPrefetch,\n        url: nextUrl,\n        requestInit: args[1],\n      })\n    }\n\n    return response\n  }\n\n  return prefetchClient\n}\n\nexport const requiredElectricResponseHeaders = [\n  `electric-offset`,\n  `electric-handle`,\n]\n\nexport const requiredLiveResponseHeaders = [`electric-cursor`]\n\nexport const requiredNonLiveResponseHeaders = [`electric-schema`]\n\nexport function createFetchWithResponseHeadersCheck(\n  fetchClient: typeof fetch\n): typeof fetch {\n  return async (...args: Parameters<typeof fetchClient>) => {\n    const response = await fetchClient(...args)\n\n    if (response.ok) {\n      // Check that the necessary Electric headers are present on the response\n      const headers = response.headers\n      const missingHeaders: Array<string> = []\n\n      const addMissingHeaders = (requiredHeaders: Array<string>) =>\n        missingHeaders.push(...requiredHeaders.filter((h) => !headers.has(h)))\n      addMissingHeaders(requiredElectricResponseHeaders)\n\n      const input = args[0]\n      const urlString = input.toString()\n      const url = new URL(urlString)\n      if (url.searchParams.get(LIVE_QUERY_PARAM) === `true`) {\n        addMissingHeaders(requiredLiveResponseHeaders)\n      }\n\n      if (\n        !url.searchParams.has(LIVE_QUERY_PARAM) ||\n        url.searchParams.get(LIVE_QUERY_PARAM) === `false`\n      ) {\n        addMissingHeaders(requiredNonLiveResponseHeaders)\n      }\n\n      if (missingHeaders.length > 0) {\n        throw new MissingHeadersError(urlString, missingHeaders)\n      }\n    }\n\n    return response\n  }\n}\n\nclass PrefetchQueue {\n  readonly #fetchClient: typeof fetch\n  readonly #maxPrefetchedRequests: number\n  readonly #prefetchQueue = new Map<\n    string,\n    [Promise<Response>, AbortController]\n  >()\n  #queueHeadUrl: string | void\n  #queueTailUrl: string | void\n\n  constructor(options: {\n    url: Parameters<typeof fetch>[0]\n    requestInit: Parameters<typeof fetch>[1]\n    maxPrefetchedRequests: number\n    fetchClient?: typeof fetch\n  }) {\n    this.#fetchClient =\n      options.fetchClient ??\n      ((...args: Parameters<typeof fetch>) => fetch(...args))\n    this.#maxPrefetchedRequests = options.maxPrefetchedRequests\n    this.#queueHeadUrl = options.url.toString()\n    this.#queueTailUrl = this.#queueHeadUrl\n    this.#prefetch(options.url, options.requestInit)\n  }\n\n  abort(): void {\n    this.#prefetchQueue.forEach(([_, aborter]) => aborter.abort())\n  }\n\n  consume(...args: Parameters<typeof fetch>): Promise<Response> | void {\n    const url = args[0].toString()\n\n    const request = this.#prefetchQueue.get(url)?.[0]\n    // only consume if request is in queue and is the queue \"head\"\n    // if request is in the queue but not the head, the queue is being\n    // consumed out of order and should be restarted\n    if (!request || url !== this.#queueHeadUrl) return\n    this.#prefetchQueue.delete(url)\n\n    // fire off new prefetch since request has been consumed\n    request\n      .then((response) => {\n        const nextUrl = getNextChunkUrl(url, response)\n        this.#queueHeadUrl = nextUrl\n        if (\n          this.#queueTailUrl &&\n          !this.#prefetchQueue.has(this.#queueTailUrl)\n        ) {\n          this.#prefetch(this.#queueTailUrl, args[1])\n        }\n      })\n      .catch(() => {})\n\n    return request\n  }\n\n  #prefetch(...args: Parameters<typeof fetch>): void {\n    const url = args[0].toString()\n\n    // only prefetch when queue is not full\n    if (this.#prefetchQueue.size >= this.#maxPrefetchedRequests) return\n\n    // initialize aborter per request, to avoid aborting consumed requests that\n    // are still streaming their bodies to the consumer\n    const aborter = new AbortController()\n\n    try {\n      const { signal, cleanup } = chainAborter(aborter, args[1]?.signal)\n      const request = this.#fetchClient(url, { ...(args[1] ?? {}), signal })\n      this.#prefetchQueue.set(url, [request, aborter])\n      request\n        .then((response) => {\n          // only keep prefetching if response chain is uninterrupted\n          if (!response.ok || aborter.signal.aborted) return\n\n          const nextUrl = getNextChunkUrl(url, response)\n\n          // only prefetch when there is a next URL\n          if (!nextUrl || nextUrl === url) {\n            this.#queueTailUrl = undefined\n            return\n          }\n\n          this.#queueTailUrl = nextUrl\n          return this.#prefetch(nextUrl, args[1])\n        })\n        .catch(() => {})\n        .finally(cleanup)\n    } catch (_) {\n      // ignore prefetch errors\n    }\n  }\n}\n\n/**\n * Generate the next chunk's URL if the url and response are valid\n */\nfunction getNextChunkUrl(url: string, res: Response): string | void {\n  const shapeHandle = res.headers.get(SHAPE_HANDLE_HEADER)\n  const lastOffset = res.headers.get(CHUNK_LAST_OFFSET_HEADER)\n  const isUpToDate = res.headers.has(CHUNK_UP_TO_DATE_HEADER)\n\n  // only prefetch if shape handle and offset for next chunk are available, and\n  // response is not already up-to-date\n  if (!shapeHandle || !lastOffset || isUpToDate) return\n\n  const nextUrl = new URL(url)\n\n  // don't prefetch live requests, rushing them will only\n  // potentially miss more recent data\n  if (nextUrl.searchParams.has(LIVE_QUERY_PARAM)) return\n\n  nextUrl.searchParams.set(SHAPE_HANDLE_QUERY_PARAM, shapeHandle)\n  nextUrl.searchParams.set(OFFSET_QUERY_PARAM, lastOffset)\n  nextUrl.searchParams.sort()\n  return nextUrl.toString()\n}\n\n/**\n * Chains an abort controller on an optional source signal's\n * aborted state - if the source signal is aborted, the provided abort\n * controller will also abort\n */\nfunction chainAborter(\n  aborter: AbortController,\n  sourceSignal?: AbortSignal | null\n): {\n  signal: AbortSignal\n  cleanup: () => void\n} {\n  let cleanup = noop\n  if (!sourceSignal) {\n    // no-op, nothing to chain to\n  } else if (sourceSignal.aborted) {\n    // source signal is already aborted, abort immediately\n    aborter.abort()\n  } else {\n    // chain to source signal abort event, and add callback to unlink\n    // the aborter to avoid memory leaks\n    const abortParent = () => aborter.abort()\n    sourceSignal.addEventListener(`abort`, abortParent, {\n      once: true,\n      signal: aborter.signal,\n    })\n    cleanup = () => sourceSignal.removeEventListener(`abort`, abortParent)\n  }\n\n  return {\n    signal: aborter.signal,\n    cleanup,\n  }\n}\n\nfunction noop() {}\n","import {\n  Message,\n  Offset,\n  Schema,\n  Row,\n  MaybePromise,\n  GetExtensions,\n} from './types'\nimport { MessageParser, Parser } from './parser'\nimport { getOffset, isUpToDateMessage } from './helpers'\nimport {\n  FetchError,\n  FetchBackoffAbortError,\n  MissingShapeUrlError,\n  InvalidSignalError,\n  MissingShapeHandleError,\n  ReservedParamError,\n} from './error'\nimport {\n  BackoffDefaults,\n  BackoffOptions,\n  createFetchWithBackoff,\n  createFetchWithChunkBuffer,\n  createFetchWithConsumedMessages,\n  createFetchWithResponseHeadersCheck,\n} from './fetch'\nimport {\n  CHUNK_LAST_OFFSET_HEADER,\n  LIVE_CACHE_BUSTER_HEADER,\n  LIVE_CACHE_BUSTER_QUERY_PARAM,\n  COLUMNS_QUERY_PARAM,\n  LIVE_QUERY_PARAM,\n  OFFSET_QUERY_PARAM,\n  SHAPE_HANDLE_HEADER,\n  SHAPE_HANDLE_QUERY_PARAM,\n  SHAPE_SCHEMA_HEADER,\n  WHERE_QUERY_PARAM,\n  WHERE_PARAMS_PARAM,\n  TABLE_QUERY_PARAM,\n  REPLICA_PARAM,\n  FORCE_DISCONNECT_AND_REFRESH,\n  PAUSE_STREAM,\n  EXPERIMENTAL_LIVE_SSE_QUERY_PARAM,\n} from './constants'\nimport {\n  EventSourceMessage,\n  fetchEventSource,\n} from '@microsoft/fetch-event-source'\n\nconst RESERVED_PARAMS: Set<ReservedParamKeys> = new Set([\n  LIVE_CACHE_BUSTER_QUERY_PARAM,\n  SHAPE_HANDLE_QUERY_PARAM,\n  LIVE_QUERY_PARAM,\n  OFFSET_QUERY_PARAM,\n])\n\ntype Replica = `full` | `default`\n\n/**\n * PostgreSQL-specific shape parameters that can be provided externally\n */\nexport interface PostgresParams<T extends Row<unknown> = Row> {\n  /** The root table for the shape. Not required if you set the table in your proxy. */\n  table?: string\n\n  /**\n   * The columns to include in the shape.\n   * Must include primary keys, and can only include valid columns.\n   * Defaults to all columns of the type `T`. If provided, must include primary keys, and can only include valid columns.\n\n   */\n  columns?: (keyof T)[]\n\n  /** The where clauses for the shape */\n  where?: string\n\n  /**\n   * Positional where clause paramater values. These will be passed to the server\n   * and will substitute `$i` parameters in the where clause.\n   *\n   * It can be an array (note that positional arguments start at 1, the array will be mapped\n   * accordingly), or an object with keys matching the used positional parameters in the where clause.\n   *\n   * If where clause is `id = $1 or id = $2`, params must have keys `\"1\"` and `\"2\"`, or be an array with length 2.\n   */\n  params?: Record<`${number}`, string> | string[]\n\n  /**\n   * If `replica` is `default` (the default) then Electric will only send the\n   * changed columns in an update.\n   *\n   * If it's `full` Electric will send the entire row with both changed and\n   * unchanged values. `old_value` will also be present on update messages,\n   * containing the previous value for changed columns.\n   *\n   * Setting `replica` to `full` will result in higher bandwidth\n   * usage and so is not generally recommended.\n   */\n  replica?: Replica\n}\ntype SerializableParamValue = string | string[] | Record<string, string>\ntype ParamValue =\n  | SerializableParamValue\n  | (() => SerializableParamValue | Promise<SerializableParamValue>)\n\n/**\n * External params type - what users provide.\n * Excludes reserved parameters to prevent dynamic variations that could cause stream shape changes.\n */\nexport type ExternalParamsRecord<T extends Row<unknown> = Row> = {\n  [K in string]: ParamValue | undefined\n} & Partial<PostgresParams<T>> & { [K in ReservedParamKeys]?: never }\n\ntype ReservedParamKeys =\n  | typeof LIVE_CACHE_BUSTER_QUERY_PARAM\n  | typeof SHAPE_HANDLE_QUERY_PARAM\n  | typeof LIVE_QUERY_PARAM\n  | typeof OFFSET_QUERY_PARAM\n\n/**\n * External headers type - what users provide.\n * Allows string or function values for any header.\n */\nexport type ExternalHeadersRecord = {\n  [key: string]: string | (() => string | Promise<string>)\n}\n\n/**\n * Internal params type - used within the library.\n * All values are converted to strings.\n */\ntype InternalParamsRecord = {\n  [K in string as K extends ReservedParamKeys ? never : K]:\n    | string\n    | Record<string, string>\n}\n\n/**\n * Helper function to resolve a function or value to its final value\n */\nexport async function resolveValue<T>(\n  value: T | (() => T | Promise<T>)\n): Promise<T> {\n  if (typeof value === `function`) {\n    return (value as () => T | Promise<T>)()\n  }\n  return value\n}\n\n/**\n * Helper function to convert external params to internal format\n */\nasync function toInternalParams(\n  params: ExternalParamsRecord<Row>\n): Promise<InternalParamsRecord> {\n  const entries = Object.entries(params)\n  const resolvedEntries = await Promise.all(\n    entries.map(async ([key, value]) => {\n      if (value === undefined) return [key, undefined]\n      const resolvedValue = await resolveValue(value)\n      return [\n        key,\n        Array.isArray(resolvedValue) ? resolvedValue.join(`,`) : resolvedValue,\n      ]\n    })\n  )\n\n  return Object.fromEntries(\n    resolvedEntries.filter(([_, value]) => value !== undefined)\n  )\n}\n\n/**\n * Helper function to resolve headers\n */\nasync function resolveHeaders(\n  headers?: ExternalHeadersRecord\n): Promise<Record<string, string>> {\n  if (!headers) return {}\n\n  const entries = Object.entries(headers)\n  const resolvedEntries = await Promise.all(\n    entries.map(async ([key, value]) => [key, await resolveValue(value)])\n  )\n\n  return Object.fromEntries(resolvedEntries)\n}\n\ntype RetryOpts = {\n  params?: ExternalParamsRecord\n  headers?: ExternalHeadersRecord\n}\n\ntype ShapeStreamErrorHandler = (\n  error: Error\n) => void | RetryOpts | Promise<void | RetryOpts>\n\n/**\n * Options for constructing a ShapeStream.\n */\nexport interface ShapeStreamOptions<T = never> {\n  /**\n   * The full URL to where the Shape is served. This can either be the Electric server\n   * directly or a proxy. E.g. for a local Electric instance, you might set `http://localhost:3000/v1/shape`\n   */\n  url: string\n\n  /**\n   * The \"offset\" on the shape log. This is typically not set as the ShapeStream\n   * will handle this automatically. A common scenario where you might pass an offset\n   * is if you're maintaining a local cache of the log. If you've gone offline\n   * and are re-starting a ShapeStream to catch-up to the latest state of the Shape,\n   * you'd pass in the last offset and shapeHandle you'd seen from the Electric server\n   * so it knows at what point in the shape to catch you up from.\n   */\n  offset?: Offset\n\n  /**\n   * Similar to `offset`, this isn't typically used unless you're maintaining\n   * a cache of the shape log.\n   */\n  handle?: string\n\n  /**\n   * HTTP headers to attach to requests made by the client.\n   * Values can be strings or functions (sync or async) that return strings.\n   * Function values are resolved in parallel when needed, making this useful\n   * for authentication tokens or other dynamic headers.\n   */\n  headers?: ExternalHeadersRecord\n\n  /**\n   * Additional request parameters to attach to the URL.\n   * Values can be strings, string arrays, or functions (sync or async) that return these types.\n   * Function values are resolved in parallel when needed, making this useful\n   * for user-specific parameters or dynamic filters.\n   *\n   * These will be merged with Electric's standard parameters.\n   * Note: You cannot use Electric's reserved parameter names\n   * (offset, handle, live, cursor).\n   *\n   * PostgreSQL-specific options like table, where, columns, and replica\n   * should be specified here.\n   */\n  params?: ExternalParamsRecord\n\n  /**\n   * Automatically fetch updates to the Shape. If you just want to sync the current\n   * shape and stop, pass false.\n   */\n  subscribe?: boolean\n\n  /**\n   * Experimental support for Server-Sent Events (SSE) for live updates.\n   */\n  experimentalLiveSse?: boolean\n\n  signal?: AbortSignal\n  fetchClient?: typeof fetch\n  backoffOptions?: BackoffOptions\n  parser?: Parser<T>\n\n  /**\n   * A function for handling shapestream errors.\n   * This is optional, when it is not provided any shapestream errors will be thrown.\n   * If the function returns an object containing parameters and/or headers\n   * the shapestream will apply those changes and try syncing again.\n   * If the function returns void the shapestream is stopped.\n   */\n  onError?: ShapeStreamErrorHandler\n}\n\nexport interface ShapeStreamInterface<T extends Row<unknown> = Row> {\n  subscribe(\n    callback: (\n      messages: Message<T>[]\n    ) => MaybePromise<void> | { columns?: (keyof T)[] },\n    onError?: (error: FetchError | Error) => void\n  ): () => void\n  unsubscribeAll(): void\n\n  isLoading(): boolean\n  lastSyncedAt(): number | undefined\n  lastSynced(): number\n  isConnected(): boolean\n  hasStarted(): boolean\n\n  isUpToDate: boolean\n  lastOffset: Offset\n  shapeHandle?: string\n  error?: unknown\n\n  forceDisconnectAndRefresh(): Promise<void>\n}\n\n/**\n * Reads updates to a shape from Electric using HTTP requests and long polling or\n * Server-Sent Events (SSE).\n * Notifies subscribers when new messages come in. Doesn't maintain any history of the\n * log but does keep track of the offset position and is the best way\n * to consume the HTTP `GET /v1/shape` api.\n *\n * @constructor\n * @param {ShapeStreamOptions} options - configure the shape stream\n * @example\n * Register a callback function to subscribe to the messages.\n * ```\n * const stream = new ShapeStream(options)\n * stream.subscribe(messages => {\n *   // messages is 1 or more row updates\n * })\n * ```\n *\n * To use Server-Sent Events (SSE) for real-time updates:\n * ```\n * const stream = new ShapeStream({\n *   url: `http://localhost:3000/v1/shape`,\n *   experimentalLiveSse: true\n * })\n * ```\n *\n * To abort the stream, abort the `signal`\n * passed in via the `ShapeStreamOptions`.\n * ```\n * const aborter = new AbortController()\n * const issueStream = new ShapeStream({\n *   url: `${BASE_URL}/${table}`\n *   subscribe: true,\n *   signal: aborter.signal,\n * })\n * // Later...\n * aborter.abort()\n * ```\n */\n\nexport class ShapeStream<T extends Row<unknown> = Row>\n  implements ShapeStreamInterface<T>\n{\n  static readonly Replica = {\n    FULL: `full` as Replica,\n    DEFAULT: `default` as Replica,\n  }\n\n  readonly options: ShapeStreamOptions<GetExtensions<T>>\n  #error: unknown = null\n\n  readonly #fetchClient: typeof fetch\n  readonly #sseFetchClient: typeof fetch\n  readonly #messageParser: MessageParser<T>\n\n  readonly #subscribers = new Map<\n    number,\n    [\n      (messages: Message<T>[]) => MaybePromise<void>,\n      ((error: Error) => void) | undefined,\n    ]\n  >()\n\n  #started = false\n  #state = `active` as `active` | `pause-requested` | `paused`\n  #lastOffset: Offset\n  #liveCacheBuster: string // Seconds since our Electric Epoch 😎\n  #lastSyncedAt?: number // unix time\n  #isUpToDate: boolean = false\n  #connected: boolean = false\n  #shapeHandle?: string\n  #schema?: Schema\n  #onError?: ShapeStreamErrorHandler\n  #requestAbortController?: AbortController\n  #isRefreshing = false\n  #tickPromise?: Promise<void>\n  #tickPromiseResolver?: () => void\n  #tickPromiseRejecter?: (reason?: unknown) => void\n  #messageChain = Promise.resolve<void[]>([]) // promise chain for incoming messages\n\n  constructor(options: ShapeStreamOptions<GetExtensions<T>>) {\n    this.options = { subscribe: true, ...options }\n    validateOptions(this.options)\n    this.#lastOffset = this.options.offset ?? `-1`\n    this.#liveCacheBuster = ``\n    this.#shapeHandle = this.options.handle\n    this.#messageParser = new MessageParser<T>(options.parser)\n    this.#onError = this.options.onError\n\n    const baseFetchClient =\n      options.fetchClient ??\n      ((...args: Parameters<typeof fetch>) => fetch(...args))\n\n    const backOffOpts = {\n      ...(options.backoffOptions ?? BackoffDefaults),\n      onFailedAttempt: () => {\n        this.#connected = false\n        options.backoffOptions?.onFailedAttempt?.()\n      },\n    }\n    const fetchWithBackoffClient = createFetchWithBackoff(\n      baseFetchClient,\n      backOffOpts\n    )\n\n    this.#sseFetchClient = createFetchWithResponseHeadersCheck(\n      createFetchWithChunkBuffer(fetchWithBackoffClient)\n    )\n\n    this.#fetchClient = createFetchWithConsumedMessages(this.#sseFetchClient)\n\n    this.#subscribeToVisibilityChanges()\n  }\n\n  get shapeHandle() {\n    return this.#shapeHandle\n  }\n\n  get error() {\n    return this.#error\n  }\n\n  get isUpToDate() {\n    return this.#isUpToDate\n  }\n\n  get lastOffset() {\n    return this.#lastOffset\n  }\n\n  async #start(): Promise<void> {\n    this.#started = true\n\n    try {\n      await this.#requestShape()\n    } catch (err) {\n      this.#error = err\n      if (this.#onError) {\n        const retryOpts = await this.#onError(err as Error)\n        if (typeof retryOpts === `object`) {\n          this.#reset()\n\n          if (`params` in retryOpts) {\n            this.options.params = retryOpts.params\n          }\n\n          if (`headers` in retryOpts) {\n            this.options.headers = retryOpts.headers\n          }\n\n          // Restart\n          this.#started = false\n          this.#start()\n        }\n        return\n      }\n\n      // If no handler is provided for errors just throw so the error still bubbles up.\n      throw err\n    } finally {\n      this.#connected = false\n      this.#tickPromiseRejecter?.()\n    }\n  }\n\n  async #requestShape(): Promise<void> {\n    if (this.#state === `pause-requested`) {\n      this.#state = `paused`\n\n      return\n    }\n\n    if (\n      !this.options.subscribe &&\n      (this.options.signal?.aborted || this.#isUpToDate)\n    ) {\n      return\n    }\n\n    const resumingFromPause = this.#state === `paused`\n    this.#state = `active`\n\n    const { url, signal } = this.options\n    const { fetchUrl, requestHeaders } = await this.#constructUrl(\n      url,\n      resumingFromPause\n    )\n    const abortListener = await this.#createAbortListener(signal)\n    const requestAbortController = this.#requestAbortController! // we know that it is not undefined because it is set by `this.#createAbortListener`\n\n    try {\n      await this.#fetchShape({\n        fetchUrl,\n        requestAbortController,\n        headers: requestHeaders,\n        resumingFromPause,\n      })\n    } catch (e) {\n      // Handle abort error triggered by refresh\n      if (\n        (e instanceof FetchError || e instanceof FetchBackoffAbortError) &&\n        requestAbortController.signal.aborted &&\n        requestAbortController.signal.reason === FORCE_DISCONNECT_AND_REFRESH\n      ) {\n        // Start a new request\n        return this.#requestShape()\n      }\n\n      if (e instanceof FetchBackoffAbortError) {\n        if (\n          requestAbortController.signal.aborted &&\n          requestAbortController.signal.reason === PAUSE_STREAM\n        ) {\n          this.#state = `paused`\n        }\n        return // interrupted\n      }\n      if (!(e instanceof FetchError)) throw e // should never happen\n\n      if (e.status == 409) {\n        // Upon receiving a 409, we should start from scratch\n        // with the newly provided shape handle\n        const newShapeHandle = e.headers[SHAPE_HANDLE_HEADER]\n        this.#reset(newShapeHandle)\n        await this.#publish(e.json as Message<T>[])\n        return this.#requestShape()\n      } else {\n        // Notify subscribers\n        this.#sendErrorToSubscribers(e)\n\n        // errors that have reached this point are not actionable without\n        // additional user input, such as 400s or failures to read the\n        // body of a response, so we exit the loop\n        throw e\n      }\n    } finally {\n      if (abortListener && signal) {\n        signal.removeEventListener(`abort`, abortListener)\n      }\n      this.#requestAbortController = undefined\n    }\n\n    this.#tickPromiseResolver?.()\n    return this.#requestShape()\n  }\n\n  async #constructUrl(url: string, resumingFromPause: boolean) {\n    // Resolve headers and params in parallel\n    const [requestHeaders, params] = await Promise.all([\n      resolveHeaders(this.options.headers),\n      this.options.params\n        ? toInternalParams(convertWhereParamsToObj(this.options.params))\n        : undefined,\n    ])\n\n    // Validate params after resolution\n    if (params) {\n      validateParams(params)\n    }\n\n    const fetchUrl = new URL(url)\n\n    // Add PostgreSQL-specific parameters\n    if (params) {\n      if (params.table) setQueryParam(fetchUrl, TABLE_QUERY_PARAM, params.table)\n      if (params.where) setQueryParam(fetchUrl, WHERE_QUERY_PARAM, params.where)\n      if (params.columns)\n        setQueryParam(fetchUrl, COLUMNS_QUERY_PARAM, params.columns)\n      if (params.replica) setQueryParam(fetchUrl, REPLICA_PARAM, params.replica)\n      if (params.params)\n        setQueryParam(fetchUrl, WHERE_PARAMS_PARAM, params.params)\n\n      // Add any remaining custom parameters\n      const customParams = { ...params }\n      delete customParams.table\n      delete customParams.where\n      delete customParams.columns\n      delete customParams.replica\n      delete customParams.params\n\n      for (const [key, value] of Object.entries(customParams)) {\n        setQueryParam(fetchUrl, key, value)\n      }\n    }\n\n    // Add Electric's internal parameters\n    fetchUrl.searchParams.set(OFFSET_QUERY_PARAM, this.#lastOffset)\n\n    if (this.#isUpToDate) {\n      // If we are resuming from a paused state, we don't want to perform a live request\n      // because it could be a long poll that holds for 20sec\n      // and during all that time `isConnected` will be false\n      if (!this.#isRefreshing && !resumingFromPause) {\n        fetchUrl.searchParams.set(LIVE_QUERY_PARAM, `true`)\n      }\n      fetchUrl.searchParams.set(\n        LIVE_CACHE_BUSTER_QUERY_PARAM,\n        this.#liveCacheBuster\n      )\n    }\n\n    if (this.#shapeHandle) {\n      // This should probably be a header for better cache breaking?\n      fetchUrl.searchParams.set(SHAPE_HANDLE_QUERY_PARAM, this.#shapeHandle!)\n    }\n\n    // sort query params in-place for stable URLs and improved cache hits\n    fetchUrl.searchParams.sort()\n\n    return {\n      fetchUrl,\n      requestHeaders,\n    }\n  }\n\n  async #createAbortListener(signal?: AbortSignal) {\n    // Create a new AbortController for this request\n    this.#requestAbortController = new AbortController()\n\n    // If user provided a signal, listen to it and pass on the reason for the abort\n    if (signal) {\n      const abortListener = () => {\n        this.#requestAbortController?.abort(signal.reason)\n      }\n\n      signal.addEventListener(`abort`, abortListener, { once: true })\n\n      if (signal.aborted) {\n        // If the signal is already aborted, abort the request immediately\n        this.#requestAbortController?.abort(signal.reason)\n      }\n\n      return abortListener\n    }\n  }\n\n  async #onInitialResponse(response: Response) {\n    const { headers, status } = response\n    const shapeHandle = headers.get(SHAPE_HANDLE_HEADER)\n    if (shapeHandle) {\n      this.#shapeHandle = shapeHandle\n    }\n\n    const lastOffset = headers.get(CHUNK_LAST_OFFSET_HEADER)\n    if (lastOffset) {\n      this.#lastOffset = lastOffset as Offset\n    }\n\n    const liveCacheBuster = headers.get(LIVE_CACHE_BUSTER_HEADER)\n    if (liveCacheBuster) {\n      this.#liveCacheBuster = liveCacheBuster\n    }\n\n    const getSchema = (): Schema => {\n      const schemaHeader = headers.get(SHAPE_SCHEMA_HEADER)\n      return schemaHeader ? JSON.parse(schemaHeader) : {}\n    }\n    this.#schema = this.#schema ?? getSchema()\n\n    // NOTE: 204s are deprecated, the Electric server should not\n    // send these in latest versions but this is here for backwards\n    // compatibility\n    if (status === 204) {\n      // There's no content so we are live and up to date\n      this.#lastSyncedAt = Date.now()\n    }\n  }\n\n  async #onMessages(batch: Array<Message<T>>, isSseMessage = false) {\n    // Update isUpToDate\n    if (batch.length > 0) {\n      const lastMessage = batch[batch.length - 1]\n      if (isUpToDateMessage(lastMessage)) {\n        if (isSseMessage) {\n          // Only use the offset from the up-to-date message if this was an SSE message.\n          // If we would use this offset from a regular fetch, then it will be wrong\n          // and we will get an \"offset is out of bounds for this shape\" error\n          const offset = getOffset(lastMessage)\n          if (offset) {\n            this.#lastOffset = offset\n          }\n        }\n        this.#lastSyncedAt = Date.now()\n        this.#isUpToDate = true\n      }\n\n      await this.#publish(batch)\n    }\n  }\n\n  /**\n   * Fetches the shape from the server using either long polling or SSE.\n   * Upon receiving a successfull response, the #onInitialResponse method is called.\n   * Afterwards, the #onMessages method is called for all the incoming updates.\n   * @param opts - The options for the request.\n   * @returns A promise that resolves when the request is complete (i.e. the long poll receives a response or the SSE connection is closed).\n   */\n  async #fetchShape(opts: {\n    fetchUrl: URL\n    requestAbortController: AbortController\n    headers: Record<string, string>\n    resumingFromPause?: boolean\n  }): Promise<void> {\n    if (\n      this.#isUpToDate &&\n      this.options.experimentalLiveSse &&\n      !this.#isRefreshing &&\n      !opts.resumingFromPause\n    ) {\n      opts.fetchUrl.searchParams.set(EXPERIMENTAL_LIVE_SSE_QUERY_PARAM, `true`)\n      return this.#requestShapeSSE(opts)\n    }\n\n    return this.#requestShapeLongPoll(opts)\n  }\n\n  async #requestShapeLongPoll(opts: {\n    fetchUrl: URL\n    requestAbortController: AbortController\n    headers: Record<string, string>\n  }): Promise<void> {\n    const { fetchUrl, requestAbortController, headers } = opts\n    const response = await this.#fetchClient(fetchUrl.toString(), {\n      signal: requestAbortController.signal,\n      headers,\n    })\n\n    this.#connected = true\n    await this.#onInitialResponse(response)\n\n    const schema = this.#schema! // we know that it is not undefined because it is set by `this.#onInitialResponse`\n    const res = await response.text()\n    const messages = res || `[]`\n    const batch = this.#messageParser.parse<Array<Message<T>>>(messages, schema)\n\n    await this.#onMessages(batch)\n  }\n\n  async #requestShapeSSE(opts: {\n    fetchUrl: URL\n    requestAbortController: AbortController\n    headers: Record<string, string>\n  }): Promise<void> {\n    const { fetchUrl, requestAbortController, headers } = opts\n    const fetch = this.#sseFetchClient\n    try {\n      let buffer: Array<Message<T>> = []\n      await fetchEventSource(fetchUrl.toString(), {\n        headers,\n        fetch,\n        onopen: async (response: Response) => {\n          this.#connected = true\n          await this.#onInitialResponse(response)\n        },\n        onmessage: (event: EventSourceMessage) => {\n          if (event.data) {\n            // event.data is a single JSON object\n            const schema = this.#schema! // we know that it is not undefined because it is set in onopen when we call this.#onInitialResponse\n            const message = this.#messageParser.parse<Message<T>>(\n              event.data,\n              schema\n            )\n            buffer.push(message)\n\n            if (isUpToDateMessage(message)) {\n              // Flush the buffer on up-to-date message.\n              // Ensures that we only process complete batches of operations.\n              this.#onMessages(buffer, true)\n              buffer = []\n            }\n          }\n        },\n        onerror: (error: Error) => {\n          // rethrow to close the SSE connection\n          throw error\n        },\n        signal: requestAbortController.signal,\n      })\n    } catch (error) {\n      if (requestAbortController.signal.aborted) {\n        // During an SSE request, the fetch might have succeeded\n        // and we are parsing the incoming stream.\n        // If the abort happens while we're parsing the stream,\n        // then it won't be caught by our `createFetchWithBackoff` wrapper\n        // and instead we will get a raw AbortError here\n        // which we need to turn into a `FetchBackoffAbortError`\n        // such that #start handles it correctly.`\n        throw new FetchBackoffAbortError()\n      }\n      throw error\n    }\n  }\n\n  #pause() {\n    if (this.#started && this.#state === `active`) {\n      this.#state = `pause-requested`\n      this.#requestAbortController?.abort(PAUSE_STREAM)\n    }\n  }\n\n  #resume() {\n    if (this.#started && this.#state === `paused`) {\n      this.#start()\n    }\n  }\n\n  subscribe(\n    callback: (messages: Message<T>[]) => MaybePromise<void>,\n    onError: (error: Error) => void = () => {}\n  ) {\n    const subscriptionId = Math.random()\n\n    this.#subscribers.set(subscriptionId, [callback, onError])\n    if (!this.#started) this.#start()\n\n    return () => {\n      this.#subscribers.delete(subscriptionId)\n    }\n  }\n\n  unsubscribeAll(): void {\n    this.#subscribers.clear()\n  }\n\n  /** Unix time at which we last synced. Undefined when `isLoading` is true. */\n  lastSyncedAt(): number | undefined {\n    return this.#lastSyncedAt\n  }\n\n  /** Time elapsed since last sync (in ms). Infinity if we did not yet sync. */\n  lastSynced(): number {\n    if (this.#lastSyncedAt === undefined) return Infinity\n    return Date.now() - this.#lastSyncedAt\n  }\n\n  /** Indicates if we are connected to the Electric sync service. */\n  isConnected(): boolean {\n    return this.#connected\n  }\n\n  /** True during initial fetch. False afterwise.  */\n  isLoading(): boolean {\n    return !this.#isUpToDate\n  }\n\n  hasStarted(): boolean {\n    return this.#started\n  }\n\n  isPaused(): boolean {\n    return this.#state === `paused`\n  }\n\n  /** Await the next tick of the request loop */\n  async #nextTick() {\n    if (this.#tickPromise) {\n      return this.#tickPromise\n    }\n    this.#tickPromise = new Promise((resolve, reject) => {\n      this.#tickPromiseResolver = resolve\n      this.#tickPromiseRejecter = reject\n    })\n    this.#tickPromise.finally(() => {\n      this.#tickPromise = undefined\n      this.#tickPromiseResolver = undefined\n      this.#tickPromiseRejecter = undefined\n    })\n    return this.#tickPromise\n  }\n\n  /**\n   * Refreshes the shape stream.\n   * This preemptively aborts any ongoing long poll and reconnects without\n   * long polling, ensuring that the stream receives an up to date message with the\n   * latest LSN from Postgres at that point in time.\n   */\n  async forceDisconnectAndRefresh(): Promise<void> {\n    this.#isRefreshing = true\n    if (this.#isUpToDate && !this.#requestAbortController?.signal.aborted) {\n      // If we are \"up to date\", any current request will be a \"live\" request\n      // and needs to be aborted\n      this.#requestAbortController?.abort(FORCE_DISCONNECT_AND_REFRESH)\n    }\n    await this.#nextTick()\n    this.#isRefreshing = false\n  }\n\n  async #publish(messages: Message<T>[]): Promise<void[]> {\n    // We process messages asynchronously\n    // but SSE's `onmessage` handler is synchronous.\n    // We use a promise chain to ensure that the handlers\n    // execute sequentially in the order the messages were received.\n    this.#messageChain = this.#messageChain.then(() =>\n      Promise.all(\n        Array.from(this.#subscribers.values()).map(async ([callback, __]) => {\n          try {\n            await callback(messages)\n          } catch (err) {\n            queueMicrotask(() => {\n              throw err\n            })\n          }\n        })\n      )\n    )\n\n    return this.#messageChain\n  }\n\n  #sendErrorToSubscribers(error: Error) {\n    this.#subscribers.forEach(([_, errorFn]) => {\n      errorFn?.(error)\n    })\n  }\n\n  #subscribeToVisibilityChanges() {\n    if (\n      typeof document === `object` &&\n      typeof document.hidden === `boolean` &&\n      typeof document.addEventListener === `function`\n    ) {\n      const visibilityHandler = () => {\n        if (document.hidden) {\n          this.#pause()\n        } else {\n          this.#resume()\n        }\n      }\n\n      document.addEventListener(`visibilitychange`, visibilityHandler)\n    }\n  }\n\n  /**\n   * Resets the state of the stream, optionally with a provided\n   * shape handle\n   */\n  #reset(handle?: string) {\n    this.#lastOffset = `-1`\n    this.#liveCacheBuster = ``\n    this.#shapeHandle = handle\n    this.#isUpToDate = false\n    this.#connected = false\n    this.#schema = undefined\n  }\n}\n\n/**\n * Validates that no reserved parameter names are used in the provided params object\n * @throws {ReservedParamError} if any reserved parameter names are found\n */\nfunction validateParams(params: Record<string, unknown> | undefined): void {\n  if (!params) return\n\n  const reservedParams = Object.keys(params).filter((key) =>\n    RESERVED_PARAMS.has(key as ReservedParamKeys)\n  )\n  if (reservedParams.length > 0) {\n    throw new ReservedParamError(reservedParams)\n  }\n}\n\nfunction validateOptions<T>(options: Partial<ShapeStreamOptions<T>>): void {\n  if (!options.url) {\n    throw new MissingShapeUrlError()\n  }\n  if (options.signal && !(options.signal instanceof AbortSignal)) {\n    throw new InvalidSignalError()\n  }\n\n  if (\n    options.offset !== undefined &&\n    options.offset !== `-1` &&\n    !options.handle\n  ) {\n    throw new MissingShapeHandleError()\n  }\n\n  validateParams(options.params)\n\n  return\n}\n\n// `unknown` being in the value is a bit of defensive programming if user doesn't use TS\nfunction setQueryParam(\n  url: URL,\n  key: string,\n  value: Record<string, string> | string | unknown\n): void {\n  if (value === undefined || value == null) {\n    return\n  } else if (typeof value === `string`) {\n    url.searchParams.set(key, value)\n  } else if (typeof value === `object`) {\n    for (const [k, v] of Object.entries(value)) {\n      url.searchParams.set(`${key}[${k}]`, v)\n    }\n  } else {\n    url.searchParams.set(key, value.toString())\n  }\n}\n\nfunction convertWhereParamsToObj(\n  allPgParams: ExternalParamsRecord<Row>\n): ExternalParamsRecord<Row> {\n  if (Array.isArray(allPgParams.params)) {\n    return {\n      ...allPgParams,\n      params: Object.fromEntries(allPgParams.params.map((v, i) => [i + 1, v])),\n    }\n  }\n  return allPgParams\n}\n","import { Message, Offset, Row } from './types'\nimport { isChangeMessage, isControlMessage } from './helpers'\nimport { FetchError } from './error'\nimport { ShapeStreamInterface } from './client'\n\nexport type ShapeData<T extends Row<unknown> = Row> = Map<string, T>\nexport type ShapeChangedCallback<T extends Row<unknown> = Row> = (data: {\n  value: ShapeData<T>\n  rows: T[]\n}) => void\n\ntype ShapeStatus = `syncing` | `up-to-date`\n\n/**\n * A Shape is an object that subscribes to a shape log,\n * keeps a materialised shape `.rows` in memory and\n * notifies subscribers when the value has changed.\n *\n * It can be used without a framework and as a primitive\n * to simplify developing framework hooks.\n *\n * @constructor\n * @param {ShapeStream<T extends Row>} - the underlying shape stream\n * @example\n * ```\n * const shapeStream = new ShapeStream<{ foo: number }>({\n *   url: `http://localhost:3000/v1/shape`,\n *   params: {\n *     table: `foo`\n *   }\n * })\n * const shape = new Shape(shapeStream)\n * ```\n *\n * `rows` returns a promise that resolves the Shape data once the Shape has been\n * fully loaded (and when resuming from being offline):\n *\n *     const rows = await shape.rows\n *\n * `currentRows` returns the current data synchronously:\n *\n *     const rows = shape.currentRows\n *\n *  Subscribe to updates. Called whenever the shape updates in Postgres.\n *\n *     shape.subscribe(({ rows }) => {\n *       console.log(rows)\n *     })\n */\nexport class Shape<T extends Row<unknown> = Row> {\n  readonly stream: ShapeStreamInterface<T>\n\n  readonly #data: ShapeData<T> = new Map()\n  readonly #subscribers = new Map<number, ShapeChangedCallback<T>>()\n  #status: ShapeStatus = `syncing`\n  #error: FetchError | false = false\n\n  constructor(stream: ShapeStreamInterface<T>) {\n    this.stream = stream\n    this.stream.subscribe(\n      this.#process.bind(this),\n      this.#handleError.bind(this)\n    )\n  }\n\n  get isUpToDate(): boolean {\n    return this.#status === `up-to-date`\n  }\n\n  get lastOffset(): Offset {\n    return this.stream.lastOffset\n  }\n\n  get handle(): string | undefined {\n    return this.stream.shapeHandle\n  }\n\n  get rows(): Promise<T[]> {\n    return this.value.then((v) => Array.from(v.values()))\n  }\n\n  get currentRows(): T[] {\n    return Array.from(this.currentValue.values())\n  }\n\n  get value(): Promise<ShapeData<T>> {\n    return new Promise((resolve, reject) => {\n      if (this.stream.isUpToDate) {\n        resolve(this.currentValue)\n      } else {\n        const unsubscribe = this.subscribe(({ value }) => {\n          unsubscribe()\n          if (this.#error) reject(this.#error)\n          resolve(value)\n        })\n      }\n    })\n  }\n\n  get currentValue() {\n    return this.#data\n  }\n\n  get error() {\n    return this.#error\n  }\n\n  /** Unix time at which we last synced. Undefined when `isLoading` is true. */\n  lastSyncedAt(): number | undefined {\n    return this.stream.lastSyncedAt()\n  }\n\n  /** Time elapsed since last sync (in ms). Infinity if we did not yet sync. */\n  lastSynced() {\n    return this.stream.lastSynced()\n  }\n\n  /** True during initial fetch. False afterwise.  */\n  isLoading() {\n    return this.stream.isLoading()\n  }\n\n  /** Indicates if we are connected to the Electric sync service. */\n  isConnected(): boolean {\n    return this.stream.isConnected()\n  }\n\n  subscribe(callback: ShapeChangedCallback<T>): () => void {\n    const subscriptionId = Math.random()\n\n    this.#subscribers.set(subscriptionId, callback)\n\n    return () => {\n      this.#subscribers.delete(subscriptionId)\n    }\n  }\n\n  unsubscribeAll(): void {\n    this.#subscribers.clear()\n  }\n\n  get numSubscribers() {\n    return this.#subscribers.size\n  }\n\n  #process(messages: Message<T>[]): void {\n    let shouldNotify = false\n\n    messages.forEach((message) => {\n      if (isChangeMessage(message)) {\n        shouldNotify = this.#updateShapeStatus(`syncing`)\n        switch (message.headers.operation) {\n          case `insert`:\n            this.#data.set(message.key, message.value)\n            break\n          case `update`:\n            this.#data.set(message.key, {\n              ...this.#data.get(message.key)!,\n              ...message.value,\n            })\n            break\n          case `delete`:\n            this.#data.delete(message.key)\n            break\n        }\n      }\n\n      if (isControlMessage(message)) {\n        switch (message.headers.control) {\n          case `up-to-date`:\n            shouldNotify = this.#updateShapeStatus(`up-to-date`)\n            break\n          case `must-refetch`:\n            this.#data.clear()\n            this.#error = false\n            shouldNotify = this.#updateShapeStatus(`syncing`)\n            break\n        }\n      }\n    })\n\n    if (shouldNotify) this.#notify()\n  }\n\n  #updateShapeStatus(status: ShapeStatus): boolean {\n    const stateChanged = this.#status !== status\n    this.#status = status\n    return stateChanged && status === `up-to-date`\n  }\n\n  #handleError(e: Error): void {\n    if (e instanceof FetchError) {\n      this.#error = e\n      this.#notify()\n    }\n  }\n\n  #notify(): void {\n    this.#subscribers.forEach((callback) => {\n      callback({ value: this.currentValue, rows: this.currentRows })\n    })\n  }\n}\n"],"mappings":"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","names":["key","value","_fetchClient","_a","_b","fetch","_subscribers","_error"]}