{"version":3,"sources":["../src/error.ts","../src/parser.ts","../src/helpers.ts","../src/constants.ts","../src/fetch.ts","../src/client.ts","../src/expired-shapes-cache.ts","../src/snapshot-tracker.ts","../src/shape.ts"],"sourcesContent":["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\nexport type TransformFunction<Extensions = never> = (\n  message: Row<Extensions>\n) => Row<Extensions>\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  private transformer?: TransformFunction<GetExtensions<T>>\n  constructor(\n    parser?: Parser<GetExtensions<T>>,\n    transformer?: TransformFunction<GetExtensions<T>>\n  ) {\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    this.transformer = transformer\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        if (this.transformer) value = this.transformer(value)\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 {\n  ChangeMessage,\n  ControlMessage,\n  Message,\n  NormalizedPgSnapshot,\n  Offset,\n  PostgresSnapshot,\n  Row,\n} 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\n/**\n * Checks if a transaction is visible in a snapshot.\n *\n * @param txid - the transaction id to check\n * @param snapshot - the information about the snapshot\n * @returns true if the transaction is visible in the snapshot\n */\nexport function isVisibleInSnapshot(\n  txid: number | bigint | `${bigint}`,\n  snapshot: PostgresSnapshot | NormalizedPgSnapshot\n): boolean {\n  const xid = BigInt(txid)\n  const xmin = BigInt(snapshot.xmin)\n  const xmax = BigInt(snapshot.xmax)\n  const xip = snapshot.xip_list.map(BigInt)\n\n  // If the transaction id is less than the minimum transaction id, it is visible in the snapshot.\n  // If the transaction id is less than the maximum transaction id and not in the list of active\n  //   transactions at the time of the snapshot, it has been committed before the snapshot was taken\n  //   and is therefore visible in the snapshot.\n  // Otherwise, it is not visible in the snapshot.\n\n  return xid < xmin || (xid < xmax && !xip.includes(xid))\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 EXPIRED_HANDLE_QUERY_PARAM = `expired_handle`\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`\n/**\n * @deprecated Use {@link LIVE_SSE_QUERY_PARAM} instead.\n */\nexport const EXPERIMENTAL_LIVE_SSE_QUERY_PARAM = `experimental_live_sse`\nexport const LIVE_SSE_QUERY_PARAM = `live_sse`\nexport const FORCE_DISCONNECT_AND_REFRESH = `force-disconnect-and-refresh`\nexport const PAUSE_STREAM = `pause-stream`\nexport const LOG_MODE_QUERY_PARAM = `log`\nexport const SUBSET_PARAM_WHERE = `subset__where`\nexport const SUBSET_PARAM_LIMIT = `subset__limit`\nexport const SUBSET_PARAM_OFFSET = `subset__offset`\nexport const SUBSET_PARAM_ORDER_BY = `subset__order_by`\nexport const SUBSET_PARAM_WHERE_PARAMS = `subset__params`\n\n// Query parameters that should be passed through when proxying Electric requests\nexport const ELECTRIC_PROTOCOL_QUERY_PARAMS: Array<string> = [\n  LIVE_QUERY_PARAM,\n  LIVE_SSE_QUERY_PARAM,\n  SHAPE_HANDLE_QUERY_PARAM,\n  OFFSET_QUERY_PARAM,\n  LIVE_CACHE_BUSTER_QUERY_PARAM,\n  EXPIRED_HANDLE_QUERY_PARAM,\n  LOG_MODE_QUERY_PARAM,\n  SUBSET_PARAM_WHERE,\n  SUBSET_PARAM_LIMIT,\n  SUBSET_PARAM_OFFSET,\n  SUBSET_PARAM_ORDER_BY,\n  SUBSET_PARAM_WHERE_PARAMS,\n]\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  SUBSET_PARAM_LIMIT,\n  SUBSET_PARAM_OFFSET,\n  SUBSET_PARAM_ORDER_BY,\n  SUBSET_PARAM_WHERE,\n  SUBSET_PARAM_WHERE_PARAMS,\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   * After reaching this, delay stays constant (e.g., retry every 60s)\n   */\n  maxDelay: number\n  multiplier: number\n  onFailedAttempt?: () => void\n  debug?: boolean\n  /**\n   * Maximum number of retry attempts before giving up.\n   * Set to Infinity (default) for indefinite retries - needed for offline scenarios\n   * where clients may go offline and come back later.\n   */\n  maxRetries?: number\n}\n\nexport const BackoffDefaults = {\n  initialDelay: 100,\n  maxDelay: 60_000, // Cap at 60s - reasonable for long-lived connections\n  multiplier: 1.3,\n  maxRetries: Infinity, // Retry forever - clients may go offline and come back\n}\n\n/**\n * Parse Retry-After header value and return delay in milliseconds\n * Supports both delta-seconds format and HTTP-date format\n * Returns 0 if header is not present or invalid\n */\nexport function parseRetryAfterHeader(retryAfter: string | undefined): number {\n  if (!retryAfter) return 0\n\n  // Try parsing as seconds (delta-seconds format)\n  const retryAfterSec = Number(retryAfter)\n  if (Number.isFinite(retryAfterSec) && retryAfterSec > 0) {\n    return retryAfterSec * 1000\n  }\n\n  // Try parsing as HTTP-date\n  const retryDate = Date.parse(retryAfter)\n  if (!isNaN(retryDate)) {\n    // Handle clock skew: clamp to non-negative, cap at reasonable max\n    const deltaMs = retryDate - Date.now()\n    return Math.max(0, Math.min(deltaMs, 3600_000)) // Cap at 1 hour\n  }\n\n  return 0\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    maxRetries = Infinity,\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    while (true) {\n      try {\n        const result = await fetchClient(...args)\n        if (result.ok) {\n          return result\n        }\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          // Check max retries\n          attempt++\n          if (attempt > maxRetries) {\n            if (debug) {\n              console.log(\n                `Max retries reached (${attempt}/${maxRetries}), giving up`\n              )\n            }\n            throw e\n          }\n\n          // Calculate wait time honoring server-driven backoff as a floor\n          // Precedence: max(serverMinimum, min(clientMaxDelay, backoffWithJitter))\n\n          // 1. Parse server-provided Retry-After (if present)\n          const serverMinimumMs =\n            e instanceof FetchError && e.headers\n              ? parseRetryAfterHeader(e.headers[`retry-after`])\n              : 0\n\n          // 2. Calculate client backoff with full jitter strategy\n          // Full jitter: random_between(0, min(cap, exponential_backoff))\n          // See: https://aws.amazon.com/blogs/architecture/exponential-backoff-and-jitter/\n          const jitter = Math.random() * delay // random value between 0 and current delay\n          const clientBackoffMs = Math.min(jitter, maxDelay) // cap at maxDelay\n\n          // 3. Server minimum is the floor, client cap is the ceiling\n          const waitMs = Math.max(serverMinimumMs, clientBackoffMs)\n\n          if (debug) {\n            const source = serverMinimumMs > 0 ? `server+client` : `client`\n            console.log(\n              `Retry attempt #${attempt} after ${waitMs}ms (${source}, serverMin=${serverMinimumMs}ms, clientBackoff=${clientBackoffMs}ms)`\n            )\n          }\n\n          // Wait for the calculated duration\n          await new Promise((resolve) => setTimeout(resolve, waitMs))\n\n          // Increase the delay for the next attempt (capped at maxDelay)\n          delay = Math.min(delay * multiplier, maxDelay)\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      if (args[1]?.signal?.aborted) {\n        throw new FetchBackoffAbortError()\n      }\n\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\n      const input = args[0]\n      const urlString = input.toString()\n      const url = new URL(urlString)\n\n      // Snapshot responses (subset params) return a JSON object and do not include Electric chunk headers\n      const isSnapshotRequest = [\n        SUBSET_PARAM_WHERE,\n        SUBSET_PARAM_WHERE_PARAMS,\n        SUBSET_PARAM_LIMIT,\n        SUBSET_PARAM_OFFSET,\n        SUBSET_PARAM_ORDER_BY,\n      ].some((p) => url.searchParams.has(p))\n      if (isSnapshotRequest) {\n        return response\n      }\n\n      addMissingHeaders(requiredElectricResponseHeaders)\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  ChangeMessage,\n  SnapshotMetadata,\n} from './types'\nimport { MessageParser, Parser, TransformFunction } from './parser'\nimport { getOffset, isUpToDateMessage, isChangeMessage } 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  EXPIRED_HANDLE_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  LIVE_SSE_QUERY_PARAM,\n  ELECTRIC_PROTOCOL_QUERY_PARAMS,\n  LOG_MODE_QUERY_PARAM,\n  SUBSET_PARAM_WHERE,\n  SUBSET_PARAM_WHERE_PARAMS,\n  SUBSET_PARAM_LIMIT,\n  SUBSET_PARAM_OFFSET,\n  SUBSET_PARAM_ORDER_BY,\n} from './constants'\nimport {\n  EventSourceMessage,\n  fetchEventSource,\n} from '@microsoft/fetch-event-source'\nimport { expiredShapesCache } from './expired-shapes-cache'\nimport { SnapshotTracker } from './snapshot-tracker'\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`\nexport type LogMode = `changes_only` | `full`\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\nexport type SubsetParams = {\n  where?: string\n  params?: Record<string, string>\n  limit?: number\n  offset?: number\n  orderBy?: string\n}\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  | `subset__${string}`\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   * @deprecated No longer experimental, use {@link liveSse} instead.\n   */\n  experimentalLiveSse?: boolean\n\n  /**\n   * Use Server-Sent Events (SSE) for live updates.\n   */\n  liveSse?: boolean\n\n  /**\n   * Initial data loading mode\n   */\n  log?: LogMode\n\n  signal?: AbortSignal\n  fetchClient?: typeof fetch\n  backoffOptions?: BackoffOptions\n  parser?: Parser<T>\n  transformer?: TransformFunction<T>\n\n  /**\n   * A function for handling shapestream errors.\n   *\n   * **Automatic retries**: The client automatically retries 5xx server errors, network\n   * errors, and 429 rate limits with exponential backoff. The `onError` callback is\n   * only invoked after these automatic retries are exhausted, or for non-retryable\n   * errors like 4xx client errors.\n   *\n   * When not provided, non-retryable errors will be thrown and syncing will stop.\n   *\n   * **Return value behavior**:\n   * - Return an **object** (RetryOpts or empty `{}`) to retry syncing:\n   *   - `{}` - Retry with the same params and headers\n   *   - `{ params }` - Retry with modified params\n   *   - `{ headers }` - Retry with modified headers (e.g., refreshed auth token)\n   *   - `{ params, headers }` - Retry with both modified\n   * - Return **void** or **undefined** to stop the stream permanently\n   *\n   * **Important**: If you want syncing to continue after an error (e.g., to retry\n   * on network failures), you MUST return at least an empty object `{}`. Simply\n   * logging the error and returning nothing will stop syncing.\n   *\n   * Supports async functions that return `Promise<void | RetryOpts>`.\n   *\n   * @example\n   * ```typescript\n   * // Retry on network errors, stop on others\n   * onError: (error) => {\n   *   console.error('Stream error:', error)\n   *   if (error instanceof FetchError && error.status >= 500) {\n   *     return {} // Retry with same params\n   *   }\n   *   // Return void to stop on other errors\n   * }\n   * ```\n   *\n   * @example\n   * ```typescript\n   * // Refresh auth token on 401\n   * onError: async (error) => {\n   *   if (error instanceof FetchError && error.status === 401) {\n   *     const newToken = await refreshAuthToken()\n   *     return { headers: { Authorization: `Bearer ${newToken}` } }\n   *   }\n   *   return {} // Retry other errors\n   * }\n   * ```\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  mode: LogMode\n\n  forceDisconnectAndRefresh(): Promise<void>\n\n  requestSnapshot(params: {\n    where?: string\n    params?: Record<string, string>\n    limit: number\n    offset?: number\n    orderBy: string\n  }): Promise<{\n    metadata: SnapshotMetadata\n    data: Array<Message<T>>\n  }>\n}\n\n/**\n * Creates a canonical shape key from a URL excluding only Electric protocol parameters\n */\nfunction canonicalShapeKey(url: URL): string {\n  const cleanUrl = new URL(url.origin + url.pathname)\n\n  // Copy all params except Electric protocol ones that vary between requests\n  for (const [key, value] of url.searchParams) {\n    if (!ELECTRIC_PROTOCOL_QUERY_PARAMS.includes(key)) {\n      cleanUrl.searchParams.set(key, value)\n    }\n  }\n\n  cleanUrl.searchParams.sort()\n  return cleanUrl.toString()\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 *   liveSse: 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  #isMidStream: boolean = true\n  #connected: boolean = false\n  #shapeHandle?: string\n  #mode: LogMode\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  #snapshotTracker = new SnapshotTracker()\n  #activeSnapshotRequests = 0 // counter for concurrent snapshot requests\n  #midStreamPromise?: Promise<void>\n  #midStreamPromiseResolver?: () => void\n  #lastSseConnectionStartTime?: number\n  #minSseConnectionDuration = 1000 // Minimum expected SSE connection duration (1 second)\n  #consecutiveShortSseConnections = 0\n  #maxShortSseConnections = 3 // Fall back to long polling after this many short connections\n  #sseFallbackToLongPolling = false\n  #sseBackoffBaseDelay = 100 // Base delay for exponential backoff (ms)\n  #sseBackoffMaxDelay = 5000 // Maximum delay cap (ms)\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>(\n      options.parser,\n      options.transformer\n    )\n    this.#onError = this.options.onError\n    this.#mode = this.options.log ?? `full`\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  get mode() {\n    return this.#mode\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\n      // Check if onError handler wants to retry\n      if (this.#onError) {\n        const retryOpts = await this.#onError(err as Error)\n        // Guard against null (typeof null === \"object\" in JavaScript)\n        if (retryOpts && typeof retryOpts === `object`) {\n          // Update params/headers but don't reset offset\n          // We want to continue from where we left off, not refetch everything\n          if (retryOpts.params) {\n            // Merge new params with existing params to preserve other parameters\n            this.options.params = {\n              ...(this.options.params ?? {}),\n              ...retryOpts.params,\n            }\n          }\n\n          if (retryOpts.headers) {\n            // Merge new headers with existing headers to preserve other headers\n            this.options.headers = {\n              ...(this.options.headers ?? {}),\n              ...retryOpts.headers,\n            }\n          }\n\n          // Clear the error since we're retrying\n          this.#error = null\n\n          // Restart from current offset\n          this.#started = false\n          await this.#start()\n          return\n        }\n        // onError returned void, meaning it doesn't want to retry\n        // This is an unrecoverable error, notify subscribers\n        if (err instanceof Error) {\n          this.#sendErrorToSubscribers(err)\n        }\n        this.#connected = false\n        this.#tickPromiseRejecter?.()\n        return\n      }\n\n      // No onError handler provided, this is an unrecoverable error\n      // Notify subscribers and throw\n      if (err instanceof Error) {\n        this.#sendErrorToSubscribers(err)\n      }\n      this.#connected = false\n      this.#tickPromiseRejecter?.()\n      throw err\n    }\n\n    // Normal completion, clean up\n    this.#connected = false\n    this.#tickPromiseRejecter?.()\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, or a fallback\n        // pseudo-handle based on the current one to act as a\n        // consistent cache buster\n\n        // Store the current shape URL as expired to avoid future 409s\n        if (this.#shapeHandle) {\n          const shapeKey = canonicalShapeKey(fetchUrl)\n          expiredShapesCache.markExpired(shapeKey, this.#shapeHandle)\n        }\n\n        const newShapeHandle =\n          e.headers[SHAPE_HANDLE_HEADER] || `${this.#shapeHandle!}-next`\n        this.#reset(newShapeHandle)\n\n        // must refetch control message might be in a list or not depending\n        // on whether it came from an SSE request or long poll - handle both\n        // cases for safety here but worth revisiting 409 handling\n        await this.#publish(\n          (Array.isArray(e.json) ? e.json : [e.json]) as Message<T>[]\n        )\n        return this.#requestShape()\n      } else {\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 and let #start handle it\n        // Note: We don't notify subscribers here because onError might recover\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(\n    url: string,\n    resumingFromPause: boolean,\n    subsetParams?: SubsetParams\n  ) {\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) validateParams(params)\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    if (subsetParams) {\n      if (subsetParams.where)\n        setQueryParam(fetchUrl, SUBSET_PARAM_WHERE, subsetParams.where)\n      if (subsetParams.params)\n        setQueryParam(fetchUrl, SUBSET_PARAM_WHERE_PARAMS, subsetParams.params)\n      if (subsetParams.limit)\n        setQueryParam(fetchUrl, SUBSET_PARAM_LIMIT, subsetParams.limit)\n      if (subsetParams.offset)\n        setQueryParam(fetchUrl, SUBSET_PARAM_OFFSET, subsetParams.offset)\n      if (subsetParams.orderBy)\n        setQueryParam(fetchUrl, SUBSET_PARAM_ORDER_BY, subsetParams.orderBy)\n    }\n\n    // Add Electric's internal parameters\n    fetchUrl.searchParams.set(OFFSET_QUERY_PARAM, this.#lastOffset)\n    fetchUrl.searchParams.set(LOG_MODE_QUERY_PARAM, this.#mode)\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    // Add cache buster for shapes known to be expired to prevent 409s\n    const shapeKey = canonicalShapeKey(fetchUrl)\n    const expiredHandle = expiredShapesCache.getExpiredHandle(shapeKey)\n    if (expiredHandle) {\n      fetchUrl.searchParams.set(EXPIRED_HANDLE_QUERY_PARAM, expiredHandle)\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      // Set isMidStream to true when we receive any data\n      this.#isMidStream = true\n\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        // Set isMidStream to false when we see an up-to-date message\n        this.#isMidStream = false\n        // Resolve the promise waiting for mid-stream to end\n        this.#midStreamPromiseResolver?.()\n      }\n\n      // Filter messages using snapshot tracker\n      const messagesToProcess = batch.filter((message) => {\n        if (isChangeMessage(message)) {\n          return !this.#snapshotTracker.shouldRejectMessage(message)\n        }\n        return true // Always process control messages\n      })\n\n      await this.#publish(messagesToProcess)\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    const useSse = this.options.liveSse ?? this.options.experimentalLiveSse\n    if (\n      this.#isUpToDate &&\n      useSse &&\n      !this.#isRefreshing &&\n      !opts.resumingFromPause &&\n      !this.#sseFallbackToLongPolling\n    ) {\n      opts.fetchUrl.searchParams.set(EXPERIMENTAL_LIVE_SSE_QUERY_PARAM, `true`)\n      opts.fetchUrl.searchParams.set(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\n    // Track when the SSE connection starts\n    this.#lastSseConnectionStartTime = Date.now()\n\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    } finally {\n      // Check if the SSE connection closed too quickly\n      // This can happen when responses are cached or when the proxy/server\n      // is misconfigured for SSE and closes the connection immediately\n      const connectionDuration = Date.now() - this.#lastSseConnectionStartTime!\n      const wasAborted = requestAbortController.signal.aborted\n\n      if (connectionDuration < this.#minSseConnectionDuration && !wasAborted) {\n        // Connection was too short - likely a cached response or misconfiguration\n        this.#consecutiveShortSseConnections++\n\n        if (\n          this.#consecutiveShortSseConnections >= this.#maxShortSseConnections\n        ) {\n          // Too many short connections - fall back to long polling\n          this.#sseFallbackToLongPolling = true\n          console.warn(\n            `[Electric] SSE connections are closing immediately (possibly due to proxy buffering or misconfiguration). ` +\n              `Falling back to long polling. ` +\n              `Your proxy must support streaming SSE responses (not buffer the complete response). ` +\n              `Configuration: Nginx add 'X-Accel-Buffering: no', Caddy add 'flush_interval -1' to reverse_proxy. ` +\n              `Note: Do NOT disable caching entirely - Electric uses cache headers to enable request collapsing for efficiency.`\n          )\n        } else {\n          // Add exponential backoff with full jitter to prevent tight infinite loop\n          // Formula: random(0, min(cap, base * 2^attempt))\n          const maxDelay = Math.min(\n            this.#sseBackoffMaxDelay,\n            this.#sseBackoffBaseDelay *\n              Math.pow(2, this.#consecutiveShortSseConnections)\n          )\n          const delayMs = Math.floor(Math.random() * maxDelay)\n          await new Promise((resolve) => setTimeout(resolve, delayMs))\n        }\n      } else if (connectionDuration >= this.#minSseConnectionDuration) {\n        // Connection was healthy - reset counter\n        this.#consecutiveShortSseConnections = 0\n      }\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  /** Await until we're not in the middle of a stream (i.e., until we see an up-to-date message) */\n  async #waitForStreamEnd() {\n    if (!this.#isMidStream) {\n      return\n    }\n    if (this.#midStreamPromise) {\n      return this.#midStreamPromise\n    }\n    this.#midStreamPromise = new Promise((resolve) => {\n      this.#midStreamPromiseResolver = resolve\n    })\n    this.#midStreamPromise.finally(() => {\n      this.#midStreamPromise = undefined\n      this.#midStreamPromiseResolver = undefined\n    })\n    return this.#midStreamPromise\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.#isMidStream = true\n    this.#connected = false\n    this.#schema = undefined\n    this.#activeSnapshotRequests = 0\n    // Reset SSE fallback state to try SSE again after reset\n    this.#consecutiveShortSseConnections = 0\n    this.#sseFallbackToLongPolling = false\n  }\n\n  /**\n   * Request a snapshot for subset of data.\n   *\n   * Only available when mode is `changes_only`.\n   * Returns the insertion point & the data, but more importantly injects the data\n   * into the subscribed data stream. Returned value is unlikely to be useful for the caller,\n   * unless the caller has complicated additional logic.\n   *\n   * Data will be injected in a way that's also tracking further incoming changes, and it'll\n   * skip the ones that are already in the snapshot.\n   *\n   * @param opts - The options for the snapshot request.\n   * @returns The metadata and the data for the snapshot.\n   */\n  async requestSnapshot(opts: SubsetParams): Promise<{\n    metadata: SnapshotMetadata\n    data: Array<ChangeMessage<T>>\n  }> {\n    if (this.#mode === `full`) {\n      throw new Error(\n        `Snapshot requests are not supported in ${this.#mode} mode, as the consumer is guaranteed to observe all data`\n      )\n    }\n    // We shouldn't be getting a snapshot on a shape that's not started\n    if (!this.#started) await this.#start()\n\n    // Wait until we're not mid-stream before pausing\n    // This ensures we don't pause in the middle of a transaction\n    await this.#waitForStreamEnd()\n\n    // Pause the stream if this is the first snapshot request\n    this.#activeSnapshotRequests++\n\n    try {\n      if (this.#activeSnapshotRequests === 1) {\n        // Currently this cannot throw, but in case it can later it's in this try block to not have a stuck counter\n        this.#pause()\n      }\n\n      const { fetchUrl, requestHeaders } = await this.#constructUrl(\n        this.options.url,\n        true,\n        opts\n      )\n\n      const { metadata, data } = await this.#fetchSnapshot(\n        fetchUrl,\n        requestHeaders\n      )\n\n      const dataWithEndBoundary = (data as Array<Message<T>>).concat([\n        { headers: { control: `snapshot-end`, ...metadata } },\n      ])\n\n      this.#snapshotTracker.addSnapshot(\n        metadata,\n        new Set(data.map((message) => message.key))\n      )\n      this.#onMessages(dataWithEndBoundary, false)\n\n      return {\n        metadata,\n        data,\n      }\n    } finally {\n      // Resume the stream if this was the last snapshot request\n      this.#activeSnapshotRequests--\n      if (this.#activeSnapshotRequests === 0) {\n        this.#resume()\n      }\n    }\n  }\n\n  async #fetchSnapshot(url: URL, headers: Record<string, string>) {\n    const response = await this.#fetchClient(url.toString(), { headers })\n\n    if (!response.ok) {\n      throw new FetchError(\n        response.status,\n        undefined,\n        undefined,\n        Object.fromEntries([...response.headers.entries()]),\n        url.toString()\n      )\n    }\n\n    const { metadata, data } = await response.json()\n    const batch = this.#messageParser.parse<Array<ChangeMessage<T>>>(\n      JSON.stringify(data),\n      this.#schema!\n    )\n\n    return {\n      metadata,\n      data: batch,\n    }\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.offset !== `now` &&\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","interface ExpiredShapeCacheEntry {\n  expiredHandle: string\n  lastUsed: number\n}\n\n/**\n * LRU cache for tracking expired shapes with automatic cleanup\n */\nexport class ExpiredShapesCache {\n  private data: Record<string, ExpiredShapeCacheEntry> = {}\n  private max: number = 250\n  private readonly storageKey = `electric_expired_shapes`\n\n  getExpiredHandle(shapeUrl: string): string | null {\n    const entry = this.data[shapeUrl]\n    if (entry) {\n      // Update last used time when accessed\n      entry.lastUsed = Date.now()\n      this.save()\n      return entry.expiredHandle\n    }\n    return null\n  }\n\n  markExpired(shapeUrl: string, handle: string): void {\n    this.data[shapeUrl] = { expiredHandle: handle, lastUsed: Date.now() }\n\n    const keys = Object.keys(this.data)\n    if (keys.length > this.max) {\n      const oldest = keys.reduce((min, k) =>\n        this.data[k].lastUsed < this.data[min].lastUsed ? k : min\n      )\n      delete this.data[oldest]\n    }\n\n    this.save()\n  }\n\n  private save(): void {\n    if (typeof localStorage === `undefined`) return\n    try {\n      localStorage.setItem(this.storageKey, JSON.stringify(this.data))\n    } catch {\n      // Ignore localStorage errors\n    }\n  }\n\n  private load(): void {\n    if (typeof localStorage === `undefined`) return\n    try {\n      const stored = localStorage.getItem(this.storageKey)\n      if (stored) {\n        this.data = JSON.parse(stored)\n      }\n    } catch {\n      // Ignore localStorage errors, start fresh\n      this.data = {}\n    }\n  }\n\n  constructor() {\n    this.load()\n  }\n\n  clear(): void {\n    this.data = {}\n    this.save()\n  }\n}\n\n// Module-level singleton instance\nexport const expiredShapesCache = new ExpiredShapesCache()\n","import { isVisibleInSnapshot } from './helpers'\nimport { Row, SnapshotMetadata } from './types'\nimport { ChangeMessage } from './types'\n\n/**\n * Tracks active snapshots and filters out duplicate change messages that are already included in snapshots.\n *\n * When requesting a snapshot in changes_only mode, we need to track which transactions were included in the\n * snapshot to avoid processing duplicate changes that arrive via the live stream. This class maintains that\n * tracking state and provides methods to:\n *\n * - Add new snapshots for tracking via addSnapshot()\n * - Remove completed snapshots via removeSnapshot()\n * - Check if incoming changes should be filtered via shouldRejectMessage()\n */\nexport class SnapshotTracker {\n  private activeSnapshots: Map<\n    number,\n    { xmin: bigint; xmax: bigint; xip_list: bigint[]; keys: Set<string> }\n  > = new Map()\n  private xmaxSnapshots: Map<bigint, Set<number>> = new Map()\n  private snapshotsByDatabaseLsn: Map<bigint, Set<number>> = new Map()\n\n  /**\n   * Add a new snapshot for tracking\n   */\n  addSnapshot(metadata: SnapshotMetadata, keys: Set<string>): void {\n    this.activeSnapshots.set(metadata.snapshot_mark, {\n      xmin: BigInt(metadata.xmin),\n      xmax: BigInt(metadata.xmax),\n      xip_list: metadata.xip_list.map(BigInt),\n      keys,\n    })\n    const xmaxSet =\n      this.xmaxSnapshots\n        .get(BigInt(metadata.xmax))\n        ?.add(metadata.snapshot_mark) ?? new Set([metadata.snapshot_mark])\n    this.xmaxSnapshots.set(BigInt(metadata.xmax), xmaxSet)\n    const databaseLsnSet =\n      this.snapshotsByDatabaseLsn\n        .get(BigInt(metadata.database_lsn))\n        ?.add(metadata.snapshot_mark) ?? new Set([metadata.snapshot_mark])\n    this.snapshotsByDatabaseLsn.set(\n      BigInt(metadata.database_lsn),\n      databaseLsnSet\n    )\n  }\n\n  /**\n   * Remove a snapshot from tracking\n   */\n  removeSnapshot(snapshotMark: number): void {\n    this.activeSnapshots.delete(snapshotMark)\n  }\n\n  /**\n   * Check if a change message should be filtered because its already in an active snapshot\n   * Returns true if the message should be filtered out (not processed)\n   */\n  shouldRejectMessage(message: ChangeMessage<Row<unknown>>): boolean {\n    const txids = message.headers.txids || []\n    if (txids.length === 0) return false\n\n    const xid = Math.max(...txids) // Use the maximum transaction ID\n\n    for (const [xmax, snapshots] of this.xmaxSnapshots.entries()) {\n      if (xid >= xmax) {\n        for (const snapshot of snapshots) {\n          this.removeSnapshot(snapshot)\n        }\n      }\n    }\n\n    return [...this.activeSnapshots.values()].some(\n      (x) => x.keys.has(message.key) && isVisibleInSnapshot(xid, x)\n    )\n  }\n\n  lastSeenUpdate(newDatabaseLsn: bigint): void {\n    for (const [dbLsn, snapshots] of this.snapshotsByDatabaseLsn.entries()) {\n      if (dbLsn <= newDatabaseLsn) {\n        for (const snapshot of snapshots) {\n          this.removeSnapshot(snapshot)\n        }\n      }\n    }\n  }\n}\n","import { Message, Offset, Row } from './types'\nimport { isChangeMessage, isControlMessage } from './helpers'\nimport { FetchError } from './error'\nimport { LogMode, 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  readonly #insertedKeys = new Set<string>()\n  readonly #requestedSubSnapshots = new Set<string>()\n  #reexecuteSnapshotsPending = false\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  /** Current log mode of the underlying stream */\n  get mode(): LogMode {\n    return this.stream.mode\n  }\n\n  /**\n   * Request a snapshot for subset of data. Only available when mode is changes_only.\n   * Returns void; data will be emitted via the stream and processed by this Shape.\n   */\n  async requestSnapshot(\n    params: Parameters<ShapeStreamInterface<T>[`requestSnapshot`]>[0]\n  ): Promise<void> {\n    // Track this snapshot request for future re-execution on shape rotation\n    const key = JSON.stringify(params)\n    this.#requestedSubSnapshots.add(key)\n    // Ensure the stream is up-to-date so schema is available for parsing\n    await this.#awaitUpToDate()\n    await this.stream.requestSnapshot(params)\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        if (this.mode === `full`) {\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        } else {\n          // changes_only: only apply updates/deletes for keys for which we observed an insert\n          switch (message.headers.operation) {\n            case `insert`:\n              this.#insertedKeys.add(message.key)\n              this.#data.set(message.key, message.value)\n              break\n            case `update`:\n              if (this.#insertedKeys.has(message.key)) {\n                this.#data.set(message.key, {\n                  ...this.#data.get(message.key)!,\n                  ...message.value,\n                })\n              }\n              break\n            case `delete`:\n              if (this.#insertedKeys.has(message.key)) {\n                this.#data.delete(message.key)\n                this.#insertedKeys.delete(message.key)\n              }\n              break\n          }\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            if (this.#reexecuteSnapshotsPending) {\n              this.#reexecuteSnapshotsPending = false\n              void this.#reexecuteSnapshots()\n            }\n            break\n          case `must-refetch`:\n            this.#data.clear()\n            this.#insertedKeys.clear()\n            this.#error = false\n            shouldNotify = this.#updateShapeStatus(`syncing`)\n            // Flag to re-execute sub-snapshots once the new shape is up-to-date\n            this.#reexecuteSnapshotsPending = true\n            break\n        }\n      }\n    })\n\n    if (shouldNotify) this.#notify()\n  }\n\n  async #reexecuteSnapshots(): Promise<void> {\n    // Wait until stream is up-to-date again (ensures schema is available)\n    await this.#awaitUpToDate()\n\n    // Re-execute all snapshots concurrently\n    await Promise.all(\n      Array.from(this.#requestedSubSnapshots).map(async (jsonParams) => {\n        try {\n          const snapshot = JSON.parse(jsonParams)\n          await this.stream.requestSnapshot(snapshot)\n        } catch (_) {\n          // Ignore and continue; errors will be surfaced via stream onError\n        }\n      })\n    )\n  }\n\n  async #awaitUpToDate(): Promise<void> {\n    if (this.stream.isUpToDate) return\n    await new Promise<void>((resolve) => {\n      const check = () => {\n        if (this.stream.isUpToDate) {\n          clearInterval(interval)\n          unsub()\n          resolve()\n        }\n      }\n      const interval = setInterval(check, 10)\n      const unsub = this.stream.subscribe(\n        () => check(),\n        () => check()\n      )\n      check()\n    })\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":"svCAAO,IAAMA,EAAN,MAAMC,UAAmB,KAAM,CAMpC,YACEC,EACAC,EACAC,EACAC,EACOC,EACPC,EACA,CACA,MACEA,GACE,cAAcL,CAAM,OAAOI,CAAG,KAAKH,GAAA,KAAAA,EAAQ,KAAK,UAAUC,CAAI,CAAC,EACnE,EANO,SAAAE,EAOP,KAAK,KAAO,aACZ,KAAK,OAASJ,EACd,KAAK,KAAOC,EACZ,KAAK,KAAOC,EACZ,KAAK,QAAUC,CACjB,CAEA,OAAa,aACXG,EACAF,EACqB,QAAAG,EAAA,sBACrB,IAAMP,EAASM,EAAS,OAClBH,EAAU,OAAO,YAAY,CAAC,GAAGG,EAAS,QAAQ,QAAQ,CAAC,CAAC,EAC9DL,EACAC,EAEEM,EAAcF,EAAS,QAAQ,IAAI,cAAc,EACvD,OAAKA,EAAS,WACRE,GAAeA,EAAY,SAAS,kBAAkB,EACxDN,EAAQ,MAAMI,EAAS,KAAK,EAE5BL,EAAO,MAAMK,EAAS,KAAK,GAIxB,IAAIP,EAAWC,EAAQC,EAAMC,EAAMC,EAASC,CAAG,CACxD,GACF,EAEaK,EAAN,cAAqC,KAAM,CAChD,aAAc,CACZ,MAAM,4BAA4B,EAClC,KAAK,KAAO,wBACd,CACF,EASO,IAAMC,GAAN,cAAmC,KAAM,CAC9C,aAAc,CACZ,MAAM,uDAAuD,EAC7D,KAAK,KAAO,sBACd,CACF,EAEaC,GAAN,cAAiC,KAAM,CAC5C,aAAc,CACZ,MAAM,+DAA+D,EACrE,KAAK,KAAO,oBACd,CACF,EAEaC,GAAN,cAAsC,KAAM,CACjD,aAAc,CACZ,MACE,2EACF,EACA,KAAK,KAAO,yBACd,CACF,EAEaC,GAAN,cAAiC,KAAM,CAC5C,YAAYC,EAA0B,CACpC,MACE,kEAAkEA,EAAe,KAAK,IAAI,CAAC,EAC7F,EACA,KAAK,KAAO,oBACd,CACF,EAEaC,GAAN,cAAmC,KAAM,CAC9C,YAAYC,EAAoB,CAC9B,MAAM,WAAWA,GAAA,KAAAA,EAAc,SAAS,8BAA8B,EACtE,KAAK,KAAO,sBACd,CACF,EASO,IAAMC,GAAN,cAAkC,KAAM,CAC7C,YAAYC,EAAaC,EAA+B,CACtD,IAAIC,EAAM,yCAAyCF,CAAG;AAAA,EACtDC,EAAe,QAASE,GAAM,CAC5BD,GAAO,KAAKC,CAAC;AAAA,CACf,CAAC,EACDD,GAAO;AAAA,iHACPA,GAAO;AAAA,oGACP,MAAMA,CAAG,CACX,CACF,EC5FA,IAAME,GAAeC,GAAkB,OAAOA,CAAK,EAC7CC,GAAaD,GAAkBA,IAAU,QAAUA,IAAU,IAC7DE,GAAeF,GAAkB,OAAOA,CAAK,EAC7CG,GAAaH,GAAkB,KAAK,MAAMA,CAAK,EAC/CI,GAAiCC,GAAcA,EAExCC,GAAwB,CACnC,KAAMP,GACN,KAAMA,GACN,KAAMG,GACN,KAAMD,GACN,OAAQF,GACR,OAAQA,GACR,KAAMI,GACN,MAAOA,EACT,EAGO,SAASI,GACdP,EACAQ,EACmB,CACnB,IAAIC,EAAI,EACJC,EAAO,KACPC,EAAM,GACNC,EAAS,GACTC,EAAO,EACPC,EAEJ,SAASC,EAAaC,EAAUC,EAAeC,EAAa,CAC1D,IAAIC,EAAoBH,EAAE,MAAMC,EAAOC,CAAG,EAC1C,OAAAC,EAAMA,IAAQ,OAAS,KAAOA,EACvBX,EAASA,EAAOW,CAAG,EAAIA,CAChC,CAEA,SAASC,EAAKJ,EAAqC,CACjD,IAAMK,EAAK,CAAC,EACZ,KAAOZ,EAAIO,EAAE,OAAQP,IAAK,CAExB,GADAC,EAAOM,EAAEP,CAAC,EACNG,EACEF,IAAS,KACXC,GAAOK,EAAE,EAAEP,CAAC,EACHC,IAAS,KAClBW,EAAG,KAAKb,EAASA,EAAOG,CAAG,EAAIA,CAAG,EAClCA,EAAM,GACNC,EAASI,EAAEP,EAAI,CAAC,IAAM,IACtBI,EAAOJ,EAAI,GAEXE,GAAOD,UAEAA,IAAS,IAClBE,EAAS,WACAF,IAAS,IAClBG,EAAO,EAAEJ,EACTY,EAAG,KAAKD,EAAKJ,CAAC,CAAC,UACNN,IAAS,IAAK,CACvBE,EAAS,GACTC,EAAOJ,GAAKY,EAAG,KAAKN,EAAaC,EAAGH,EAAMJ,CAAC,CAAC,EAC5CI,EAAOJ,EAAI,EACX,KACF,MAAWC,IAAS,KAAOI,IAAM,KAAOA,IAAM,MAC5CO,EAAG,KAAKN,EAAaC,EAAGH,EAAMJ,CAAC,CAAC,EAChCI,EAAOJ,EAAI,GAEbK,EAAIJ,CACN,CACA,OAAAG,EAAOJ,GAAKY,EAAG,KAAKA,EAAG,KAAKN,EAAaC,EAAGH,EAAMJ,EAAI,CAAC,CAAC,CAAC,EAClDY,CACT,CAEA,OAAOD,EAAKpB,CAAK,EAAE,CAAC,CACtB,CAEO,IAAMsB,GAAN,KAA4C,CAGjD,YACEd,EACAe,EACA,CAIA,KAAK,OAASC,IAAA,GAAKlB,IAAkBE,GACrC,KAAK,YAAce,CACrB,CAEA,MAAcE,EAAkBC,EAAwB,CACtD,OAAO,KAAK,MAAMD,EAAU,CAACE,EAAK3B,IAAU,CAM1C,IACG2B,IAAQ,SAAWA,IAAQ,cAC5B,OAAO3B,GAAU,UACjBA,IAAU,KACV,CAEA,IAAM4B,EAAM5B,EACZ,OAAO,KAAK4B,CAAG,EAAE,QAASD,GAAQ,CAChCC,EAAID,CAAG,EAAI,KAAK,SAASA,EAAKC,EAAID,CAAG,EAAoBD,CAAM,CACjE,CAAC,EAEG,KAAK,cAAa1B,EAAQ,KAAK,YAAYA,CAAK,EACtD,CACA,OAAOA,CACT,CAAC,CACH,CAGQ,SACN2B,EACA3B,EACA0B,EACyB,CA7I7B,IAAAG,EA8II,IAAMC,EAAaJ,EAAOC,CAAG,EAC7B,GAAI,CAACG,EAGH,OAAO9B,EAIT,IAA2D+B,EAAAD,EAAnD,MAAME,EAAK,KAAMC,CAtJ7B,EAsJ+DF,EAAnBG,EAAAC,GAAmBJ,EAAnB,CAAhC,OAAW,SAKbK,GAAaP,EAAA,KAAK,OAAOG,CAAG,IAAf,KAAAH,EAAoBzB,GACjCI,EAAS6B,GAAmBD,EAAYN,EAAYH,CAAG,EAE7D,OAAIM,GAAcA,EAAa,EAECI,GAC5B,CAACrC,EAAOsC,IAAM/B,GAAcP,EAAOQ,CAAM,EACzCsB,EACAH,CACF,EAC6B3B,CAAK,EAG7BQ,EAAOR,EAAOkC,CAAc,CACrC,CACF,EAEA,SAASG,GACP7B,EACAsB,EACAS,EACmC,CAhLrC,IAAAR,EAiLE,IAAMS,EAAa,GAAET,EAAAD,EAAW,WAAX,MAAAC,GAIrB,OAAQ/B,GAAyB,CAC/B,GAAIA,IAAU,KAAM,CAClB,GAAI,CAACwC,EACH,MAAM,IAAIC,GAAqBF,GAAA,KAAAA,EAAc,SAAS,EAExD,OAAO,IACT,CACA,OAAO/B,EAAOR,EAAO8B,CAAU,CACjC,CACF,CCnKO,SAASY,GACdC,EAC6B,CAC7B,MAAO,QAASA,CAClB,CAmBO,SAASC,GACdD,EAC2B,CAC3B,MAAO,CAACD,GAAgBC,CAAO,CACjC,CAEO,SAASE,GACdF,EACkD,CAClD,OAAOC,GAAiBD,CAAO,GAAKA,EAAQ,QAAQ,UAAY,YAClE,CAOO,SAASG,GAAUH,EAA6C,CACrE,IAAMI,EAAMJ,EAAQ,QAAQ,qBAC5B,GAAKI,EAGL,MAAO,GAAGA,CAAG,IACf,CASO,SAASC,GACdC,EACAC,EACS,CACT,IAAMC,EAAM,OAAOF,CAAI,EACjBG,EAAO,OAAOF,EAAS,IAAI,EAC3BG,EAAO,OAAOH,EAAS,IAAI,EAC3BI,EAAMJ,EAAS,SAAS,IAAI,MAAM,EAQxC,OAAOC,EAAMC,GAASD,EAAME,GAAQ,CAACC,EAAI,SAASH,CAAG,CACvD,CClGO,IAAMI,GAA2B,kBAC3BC,GAAsB,kBACtBC,GAA2B,kBAC3BC,GAAsB,kBACtBC,GAA0B,sBAC1BC,GAAsB,UACtBC,GAAgC,SAChCC,GAA6B,iBAC7BC,GAA2B,SAC3BC,EAAmB,OACnBC,GAAqB,SACrBC,GAAoB,QACpBC,GAAoB,QACpBC,GAAgB,UAChBC,GAAqB,SAIrBC,GAAoC,wBACpCC,GAAuB,WACvBC,GAA+B,+BAC/BC,GAAe,eACfC,GAAuB,MACvBC,GAAqB,gBACrBC,GAAqB,gBACrBC,GAAsB,iBACtBC,GAAwB,mBACxBC,GAA4B,iBAG5BC,GAAgD,CAC3DhB,EACAO,GACAR,GACAE,GACAJ,GACAC,GACAY,GACAC,GACAC,GACAC,GACAC,GACAC,EACF,ECtBA,IAAME,GAA0B,CAAC,GAAG,EAuBvBC,GAAkB,CAC7B,aAAc,IACd,SAAU,IACV,WAAY,IACZ,WAAY,GACd,EAOO,SAASC,GAAsBC,EAAwC,CAC5E,GAAI,CAACA,EAAY,MAAO,GAGxB,IAAMC,EAAgB,OAAOD,CAAU,EACvC,GAAI,OAAO,SAASC,CAAa,GAAKA,EAAgB,EACpD,OAAOA,EAAgB,IAIzB,IAAMC,EAAY,KAAK,MAAMF,CAAU,EACvC,GAAI,CAAC,MAAME,CAAS,EAAG,CAErB,IAAMC,EAAUD,EAAY,KAAK,IAAI,EACrC,OAAO,KAAK,IAAI,EAAG,KAAK,IAAIC,EAAS,IAAQ,CAAC,CAChD,CAEA,MAAO,EACT,CAEO,SAASC,GACdC,EACAC,EAAiCR,GACnB,CACd,GAAM,CACJ,aAAAS,EACA,SAAAC,EACA,WAAAC,EACA,MAAAC,EAAQ,GACR,gBAAAC,EACA,WAAAC,EAAa,GACf,EAAIN,EACJ,MAAO,IAAUO,IAAsDC,EAAA,sBAxFzE,IAAAC,EAyFI,IAAMC,EAAMH,EAAK,CAAC,EACZI,EAAUJ,EAAK,CAAC,EAElBK,EAAQX,EACRY,EAAU,EAEd,OACE,GAAI,CACF,IAAMC,EAAS,MAAMf,EAAY,GAAGQ,CAAI,EACxC,GAAIO,EAAO,GACT,OAAOA,EAKT,MAFY,MAAMC,EAAW,aAAaD,EAAQJ,EAAI,SAAS,CAAC,CAGlE,OAASM,EAAG,CAEV,GADAX,GAAA,MAAAA,KACII,EAAAE,GAAA,YAAAA,EAAS,SAAT,MAAAF,EAAiB,QACnB,MAAM,IAAIQ,EACL,GACLD,aAAaD,GACb,CAACxB,GAAwB,SAASyB,EAAE,MAAM,GAC1CA,EAAE,QAAU,KACZA,EAAE,OAAS,IAGX,MAAMA,EACD,CAGL,GADAH,IACIA,EAAUP,EACZ,MAAIF,GACF,QAAQ,IACN,wBAAwBS,CAAO,IAAIP,CAAU,cAC/C,EAEIU,EAOR,IAAME,GACJF,aAAaD,GAAcC,EAAE,QACzBvB,GAAsBuB,EAAE,QAAQ,aAAa,CAAC,EAC9C,EAKAG,GAAS,KAAK,OAAO,EAAIP,EACzBQ,GAAkB,KAAK,IAAID,GAAQjB,CAAQ,EAG3CmB,GAAS,KAAK,IAAIH,GAAiBE,EAAe,EAExD,GAAIhB,EAAO,CACT,IAAMkB,GAASJ,GAAkB,EAAI,gBAAkB,SACvD,QAAQ,IACN,kBAAkBL,CAAO,UAAUQ,EAAM,OAAOC,EAAM,eAAeJ,EAAe,qBAAqBE,EAAe,KAC1H,CACF,CAGA,MAAM,IAAI,QAASG,IAAY,WAAWA,GAASF,EAAM,CAAC,EAG1DT,EAAQ,KAAK,IAAIA,EAAQT,EAAYD,CAAQ,CAC/C,CACF,CAEJ,EACF,CAEA,IAAMsB,GAAuB,CAAC,IAAK,IAAK,GAAG,EAGpC,SAASC,GAAgC1B,EAA2B,CACzE,MAAO,IAAUQ,IAAsDC,EAAA,sBAzKzE,IAAAC,EAAAiB,EA0KI,IAAMhB,EAAMH,EAAK,CAAC,EACZoB,EAAM,MAAM5B,EAAY,GAAGQ,CAAI,EACrC,GAAI,CACF,GAAIoB,EAAI,OAAS,KAAOH,GAAqB,SAASG,EAAI,MAAM,EAC9D,OAAOA,EAGT,IAAMC,EAAO,MAAMD,EAAI,KAAK,EAC5B,OAAO,IAAI,SAASC,EAAMD,CAAG,CAC/B,OAASE,EAAK,CACZ,MAAIH,GAAAjB,EAAAF,EAAK,CAAC,IAAN,YAAAE,EAAS,SAAT,MAAAiB,EAAiB,QACb,IAAIT,EAGN,IAAIF,EACRY,EAAI,OACJ,OACA,OACA,OAAO,YAAY,CAAC,GAAGA,EAAI,QAAQ,QAAQ,CAAC,CAAC,EAC7CjB,EAAI,SAAS,EACbmB,aAAe,MACXA,EAAI,QACJ,OAAOA,GAAQ,SACbA,EACA,qBACR,CACF,CACF,EACF,CAMA,IAAMC,GAAwB,CAC5B,oBAAqB,CACvB,EAWO,SAASC,GACdhC,EACAiC,EAAwCF,GAC1B,CACd,GAAM,CAAE,oBAAAG,CAAoB,EAAID,EAE5BE,EA6BJ,MA3BuB,IAAU3B,IAAyCC,EAAA,sBACxE,IAAME,EAAMH,EAAK,CAAC,EAAE,SAAS,EAIvB4B,EAAoBD,GAAA,YAAAA,EAAe,QAAQ,GAAG3B,GACpD,GAAI4B,EACF,OAAOA,EAGTD,GAAA,MAAAA,EAAe,QAGf,IAAME,EAAW,MAAMrC,EAAY,GAAGQ,CAAI,EACpC8B,EAAUC,GAAgB5B,EAAK0B,CAAQ,EAC7C,OAAIC,IACFH,EAAgB,IAAIK,GAAc,CAChC,YAAAxC,EACA,sBAAuBkC,EACvB,IAAKI,EACL,YAAa9B,EAAK,CAAC,CACrB,CAAC,GAGI6B,CACT,EAGF,CAEO,IAAMI,GAAkC,CAC7C,kBACA,iBACF,EAEaC,GAA8B,CAAC,iBAAiB,EAEhDC,GAAiC,CAAC,iBAAiB,EAEzD,SAASC,GACd5C,EACc,CACd,MAAO,IAAUQ,IAAyCC,EAAA,sBACxD,IAAM4B,EAAW,MAAMrC,EAAY,GAAGQ,CAAI,EAE1C,GAAI6B,EAAS,GAAI,CAEf,IAAMQ,EAAUR,EAAS,QACnBS,EAAgC,CAAC,EAEjCC,EAAqBC,GACzBF,EAAe,KAAK,GAAGE,EAAgB,OAAQC,GAAM,CAACJ,EAAQ,IAAII,CAAC,CAAC,CAAC,EAGjEC,EADQ1C,EAAK,CAAC,EACI,SAAS,EAC3BG,EAAM,IAAI,IAAIuC,CAAS,EAU7B,GAP0B,CACxBC,GACAC,GACAC,GACAC,GACAC,EACF,EAAE,KAAMC,GAAM7C,EAAI,aAAa,IAAI6C,CAAC,CAAC,EAEnC,OAAOnB,EAeT,GAZAU,EAAkBN,EAA+B,EAC7C9B,EAAI,aAAa,IAAI8C,CAAgB,IAAM,QAC7CV,EAAkBL,EAA2B,GAI7C,CAAC/B,EAAI,aAAa,IAAI8C,CAAgB,GACtC9C,EAAI,aAAa,IAAI8C,CAAgB,IAAM,UAE3CV,EAAkBJ,EAA8B,EAG9CG,EAAe,OAAS,EAC1B,MAAM,IAAIY,GAAoBR,EAAWJ,CAAc,CAE3D,CAEA,OAAOT,CACT,EACF,CAzTA,IAAAsB,GAAAC,GAAAC,EAAAC,EAAAC,EAAAC,GAAAC,GA2TMzB,GAAN,KAAoB,CAUlB,YAAY5B,EAKT,CAfLsD,EAAA,KAAAF,IACEE,EAAA,KAASP,IACTO,EAAA,KAASN,IACTM,EAAA,KAASL,EAAiB,IAAI,KAI9BK,EAAA,KAAAJ,GACAI,EAAA,KAAAH,GAnUF,IAAArD,EA2UIyD,EAAA,KAAKR,IACHjD,EAAAE,EAAQ,cAAR,KAAAF,EACC,IAAIF,IAAmC,MAAM,GAAGA,CAAI,GACvD2D,EAAA,KAAKP,GAAyBhD,EAAQ,uBACtCuD,EAAA,KAAKL,EAAgBlD,EAAQ,IAAI,SAAS,GAC1CuD,EAAA,KAAKJ,EAAgBK,EAAA,KAAKN,IAC1BO,EAAA,KAAKL,GAAAC,IAAL,UAAerD,EAAQ,IAAKA,EAAQ,YACtC,CAEA,OAAc,CACZwD,EAAA,KAAKP,GAAe,QAAQ,CAAC,CAACS,EAAGC,CAAO,IAAMA,EAAQ,MAAM,CAAC,CAC/D,CAEA,WAAW/D,EAA0D,CAxVvE,IAAAE,EAyVI,IAAMC,EAAMH,EAAK,CAAC,EAAE,SAAS,EAEvBgE,GAAU9D,EAAA0D,EAAA,KAAKP,GAAe,IAAIlD,CAAG,IAA3B,YAAAD,EAA+B,GAI/C,GAAI,GAAC8D,GAAW7D,IAAQyD,EAAA,KAAKN,IAC7B,OAAAM,EAAA,KAAKP,GAAe,OAAOlD,CAAG,EAG9B6D,EACG,KAAMnC,GAAa,CAClB,IAAMC,EAAUC,GAAgB5B,EAAK0B,CAAQ,EAC7C8B,EAAA,KAAKL,EAAgBxB,GAEnB8B,EAAA,KAAKL,IACL,CAACK,EAAA,KAAKP,GAAe,IAAIO,EAAA,KAAKL,EAAa,GAE3CM,EAAA,KAAKL,GAAAC,IAAL,UAAeG,EAAA,KAAKL,GAAevD,EAAK,CAAC,EAE7C,CAAC,EACA,MAAM,IAAM,CAAC,CAAC,EAEVgE,CACT,CAsCF,EA3FWb,GAAA,YACAC,GAAA,YACAC,EAAA,YAITC,EAAA,YACAC,EAAA,YARFC,GAAA,YAwDEC,GAAS,YAAIzD,EAAsC,CAnXrD,IAAAE,EAAAiB,EAoXI,IAAMhB,EAAMH,EAAK,CAAC,EAAE,SAAS,EAG7B,GAAI4D,EAAA,KAAKP,GAAe,MAAQO,EAAA,KAAKR,IAAwB,OAI7D,IAAMW,EAAU,IAAI,gBAEpB,GAAI,CACF,GAAM,CAAE,OAAAE,EAAQ,QAAAC,CAAQ,EAAIC,GAAaJ,GAAS7D,EAAAF,EAAK,CAAC,IAAN,YAAAE,EAAS,MAAM,EAC3D8D,EAAUJ,EAAA,KAAKT,IAAL,UAAkBhD,EAAKiE,GAAAC,EAAA,IAAMlD,EAAAnB,EAAK,CAAC,IAAN,KAAAmB,EAAW,CAAC,GAAlB,CAAsB,OAAA8C,CAAO,IACpEL,EAAA,KAAKP,GAAe,IAAIlD,EAAK,CAAC6D,EAASD,CAAO,CAAC,EAC/CC,EACG,KAAMnC,GAAa,CAElB,GAAI,CAACA,EAAS,IAAMkC,EAAQ,OAAO,QAAS,OAE5C,IAAMjC,EAAUC,GAAgB5B,EAAK0B,CAAQ,EAG7C,GAAI,CAACC,GAAWA,IAAY3B,EAAK,CAC/BwD,EAAA,KAAKJ,EAAgB,QACrB,MACF,CAEA,OAAAI,EAAA,KAAKJ,EAAgBzB,GACd+B,EAAA,KAAKL,GAAAC,IAAL,UAAe3B,EAAS9B,EAAK,CAAC,EACvC,CAAC,EACA,MAAM,IAAM,CAAC,CAAC,EACd,QAAQkE,CAAO,CACpB,OAASJ,EAAG,CAEZ,CACF,EAMF,SAAS/B,GAAgB5B,EAAaiB,EAA8B,CAClE,IAAMkD,EAAclD,EAAI,QAAQ,IAAImD,EAAmB,EACjDC,EAAapD,EAAI,QAAQ,IAAIqD,EAAwB,EACrDC,EAAatD,EAAI,QAAQ,IAAIuD,EAAuB,EAI1D,GAAI,CAACL,GAAe,CAACE,GAAcE,EAAY,OAE/C,IAAM5C,EAAU,IAAI,IAAI3B,CAAG,EAI3B,GAAI,CAAA2B,EAAQ,aAAa,IAAImB,CAAgB,EAE7C,OAAAnB,EAAQ,aAAa,IAAI8C,GAA0BN,CAAW,EAC9DxC,EAAQ,aAAa,IAAI+C,GAAoBL,CAAU,EACvD1C,EAAQ,aAAa,KAAK,EACnBA,EAAQ,SAAS,CAC1B,CAOA,SAASqC,GACPJ,EACAe,EAIA,CACA,IAAIZ,EAAUa,GACd,GAAKD,EAEE,GAAIA,EAAa,QAEtBf,EAAQ,MAAM,MACT,CAGL,IAAMiB,EAAc,IAAMjB,EAAQ,MAAM,EACxCe,EAAa,iBAAiB,QAASE,EAAa,CAClD,KAAM,GACN,OAAQjB,EAAQ,MAClB,CAAC,EACDG,EAAU,IAAMY,EAAa,oBAAoB,QAASE,CAAW,CACvE,CAEA,MAAO,CACL,OAAQjB,EAAQ,OAChB,QAAAG,CACF,CACF,CAEA,SAASa,IAAO,CAAC,CC7ZjB,OAEE,oBAAAE,OACK,gCClDA,IAAMC,GAAN,KAAyB,CAoD9B,aAAc,CAnDd,KAAQ,KAA+C,CAAC,EACxD,KAAQ,IAAc,IACtB,KAAiB,WAAa,0BAkD5B,KAAK,KAAK,CACZ,CAjDA,iBAAiBC,EAAiC,CAChD,IAAMC,EAAQ,KAAK,KAAKD,CAAQ,EAChC,OAAIC,GAEFA,EAAM,SAAW,KAAK,IAAI,EAC1B,KAAK,KAAK,EACHA,EAAM,eAER,IACT,CAEA,YAAYD,EAAkBE,EAAsB,CAClD,KAAK,KAAKF,CAAQ,EAAI,CAAE,cAAeE,EAAQ,SAAU,KAAK,IAAI,CAAE,EAEpE,IAAMC,EAAO,OAAO,KAAK,KAAK,IAAI,EAClC,GAAIA,EAAK,OAAS,KAAK,IAAK,CAC1B,IAAMC,EAASD,EAAK,OAAO,CAACE,EAAKC,IAC/B,KAAK,KAAKA,CAAC,EAAE,SAAW,KAAK,KAAKD,CAAG,EAAE,SAAWC,EAAID,CACxD,EACA,OAAO,KAAK,KAAKD,CAAM,CACzB,CAEA,KAAK,KAAK,CACZ,CAEQ,MAAa,CACnB,GAAI,OAAO,cAAiB,YAC5B,GAAI,CACF,aAAa,QAAQ,KAAK,WAAY,KAAK,UAAU,KAAK,IAAI,CAAC,CACjE,OAAQ,GAER,CACF,CAEQ,MAAa,CACnB,GAAI,OAAO,cAAiB,YAC5B,GAAI,CACF,IAAMG,EAAS,aAAa,QAAQ,KAAK,UAAU,EAC/CA,IACF,KAAK,KAAO,KAAK,MAAMA,CAAM,EAEjC,OAAQ,GAEN,KAAK,KAAO,CAAC,CACf,CACF,CAMA,OAAc,CACZ,KAAK,KAAO,CAAC,EACb,KAAK,KAAK,CACZ,CACF,EAGaC,GAAqB,IAAIT,GCxD/B,IAAMU,GAAN,KAAsB,CAAtB,cACL,KAAQ,gBAGJ,IAAI,IACR,KAAQ,cAA0C,IAAI,IACtD,KAAQ,uBAAmD,IAAI,IAK/D,YAAYC,EAA4BC,EAAyB,CA1BnE,IAAAC,EAAAC,EAAAC,EAAAC,EA2BI,KAAK,gBAAgB,IAAIL,EAAS,cAAe,CAC/C,KAAM,OAAOA,EAAS,IAAI,EAC1B,KAAM,OAAOA,EAAS,IAAI,EAC1B,SAAUA,EAAS,SAAS,IAAI,MAAM,EACtC,KAAAC,CACF,CAAC,EACD,IAAMK,GACJH,GAAAD,EAAA,KAAK,cACF,IAAI,OAAOF,EAAS,IAAI,CAAC,IAD5B,YAAAE,EAEI,IAAIF,EAAS,iBAFjB,KAAAG,EAEmC,IAAI,IAAI,CAACH,EAAS,aAAa,CAAC,EACrE,KAAK,cAAc,IAAI,OAAOA,EAAS,IAAI,EAAGM,CAAO,EACrD,IAAMC,GACJF,GAAAD,EAAA,KAAK,uBACF,IAAI,OAAOJ,EAAS,YAAY,CAAC,IADpC,YAAAI,EAEI,IAAIJ,EAAS,iBAFjB,KAAAK,EAEmC,IAAI,IAAI,CAACL,EAAS,aAAa,CAAC,EACrE,KAAK,uBAAuB,IAC1B,OAAOA,EAAS,YAAY,EAC5BO,CACF,CACF,CAKA,eAAeC,EAA4B,CACzC,KAAK,gBAAgB,OAAOA,CAAY,CAC1C,CAMA,oBAAoBC,EAA+C,CACjE,IAAMC,EAAQD,EAAQ,QAAQ,OAAS,CAAC,EACxC,GAAIC,EAAM,SAAW,EAAG,MAAO,GAE/B,IAAMC,EAAM,KAAK,IAAI,GAAGD,CAAK,EAE7B,OAAW,CAACE,EAAMC,CAAS,IAAK,KAAK,cAAc,QAAQ,EACzD,GAAIF,GAAOC,EACT,QAAWE,KAAYD,EACrB,KAAK,eAAeC,CAAQ,EAKlC,MAAO,CAAC,GAAG,KAAK,gBAAgB,OAAO,CAAC,EAAE,KACvCC,GAAMA,EAAE,KAAK,IAAIN,EAAQ,GAAG,GAAKO,GAAoBL,EAAKI,CAAC,CAC9D,CACF,CAEA,eAAeE,EAA8B,CAC3C,OAAW,CAACC,EAAOL,CAAS,IAAK,KAAK,uBAAuB,QAAQ,EACnE,GAAIK,GAASD,EACX,QAAWH,KAAYD,EACrB,KAAK,eAAeC,CAAQ,CAIpC,CACF,EFzBA,IAAMK,GAA0C,IAAI,IAAI,CACtDC,GACAC,GACAC,EACAC,EACF,CAAC,EAgGD,SAAsBC,GACpBC,EACY,QAAAC,EAAA,sBACZ,OAAI,OAAOD,GAAU,WACXA,EAA+B,EAElCA,CACT,GAKA,SAAeE,GACbC,EAC+B,QAAAF,EAAA,sBAC/B,IAAMG,EAAU,OAAO,QAAQD,CAAM,EAC/BE,EAAkB,MAAM,QAAQ,IACpCD,EAAQ,IAAWE,GAAiBL,EAAA,MAAjBK,GAAiB,UAAjB,CAACC,EAAKP,CAAK,EAAM,CAClC,GAAIA,IAAU,OAAW,MAAO,CAACO,EAAK,MAAS,EAC/C,IAAMC,EAAgB,MAAMT,GAAaC,CAAK,EAC9C,MAAO,CACLO,EACA,MAAM,QAAQC,CAAa,EAAIA,EAAc,KAAK,GAAG,EAAIA,CAC3D,CACF,EAAC,CACH,EAEA,OAAO,OAAO,YACZH,EAAgB,OAAO,CAAC,CAACI,EAAGT,CAAK,IAAMA,IAAU,MAAS,CAC5D,CACF,GAKA,SAAeU,GACbC,EACiC,QAAAV,EAAA,sBACjC,GAAI,CAACU,EAAS,MAAO,CAAC,EAEtB,IAAMP,EAAU,OAAO,QAAQO,CAAO,EAChCN,EAAkB,MAAM,QAAQ,IACpCD,EAAQ,IAAWE,GAAcL,EAAA,MAAdK,GAAc,UAAd,CAACC,EAAKP,CAAK,EAAG,CAAG,OAACO,EAAK,MAAMR,GAAaC,CAAK,CAAC,GAAC,CACtE,EAEA,OAAO,OAAO,YAAYK,CAAe,CAC3C,GAgLA,SAASO,GAAkBC,EAAkB,CAC3C,IAAMC,EAAW,IAAI,IAAID,EAAI,OAASA,EAAI,QAAQ,EAGlD,OAAW,CAACN,EAAKP,CAAK,IAAKa,EAAI,aACxBE,GAA+B,SAASR,CAAG,GAC9CO,EAAS,aAAa,IAAIP,EAAKP,CAAK,EAIxC,OAAAc,EAAS,aAAa,KAAK,EACpBA,EAAS,SAAS,CAC3B,CA7YA,IAAAE,GAAAC,GAAAC,GAAAC,EAAAC,EAAAC,EAAAC,EAAAC,EAAAC,EAAAC,EAAAC,EAAAC,EAAAC,EAAAC,EAAAC,EAAAC,EAAAC,GAAAC,EAAAC,EAAAC,EAAAC,GAAAC,EAAAC,GAAAC,GAAAC,EAAAC,EAAAC,GAAAC,GAAAC,GAAAC,EAAAC,GAAAC,GAAAC,GAAAC,GAAAC,EAAAC,GAAAC,GAAAC,GAAAC,GAAAC,GAAAC,GAAAC,GAAAC,GAAAC,GAAAC,GAAAC,GAAAC,GAAAC,GAAAC,GAAAC,GAAAC,GAAAC,GAAAC,GAubaC,GAAN,KAEP,CAmDE,YAAYC,EAA+C,CArDtDC,EAAA,KAAArB,GASLqB,EAAA,KAAAvD,GAAkB,MAElBuD,EAAA,KAAStD,IACTsD,EAAA,KAASrD,IACTqD,EAAA,KAASpD,GAEToD,EAAA,KAASnD,EAAe,IAAI,KAQ5BmD,EAAA,KAAAlD,EAAW,IACXkD,EAAA,KAAAjD,EAAS,UACTiD,EAAA,KAAAhD,GACAgD,EAAA,KAAA/C,GACA+C,EAAA,KAAA9C,GACA8C,EAAA,KAAA7C,EAAuB,IACvB6C,EAAA,KAAA5C,EAAwB,IACxB4C,EAAA,KAAA3C,EAAsB,IACtB2C,EAAA,KAAA1C,GACA0C,EAAA,KAAAzC,GACAyC,EAAA,KAAAxC,GACAwC,EAAA,KAAAvC,IACAuC,EAAA,KAAAtC,GACAsC,EAAA,KAAArC,EAAgB,IAChBqC,EAAA,KAAApC,GACAoC,EAAA,KAAAnC,IACAmC,EAAA,KAAAlC,GACAkC,EAAA,KAAAjC,GAAgB,QAAQ,QAAgB,CAAC,CAAC,GAC1CiC,EAAA,KAAAhC,GAAmB,IAAIiC,IACvBD,EAAA,KAAA/B,EAA0B,GAC1B+B,EAAA,KAAA9B,GACA8B,EAAA,KAAA7B,IACA6B,EAAA,KAAA5B,IACA4B,EAAA,KAAA3B,GAA4B,KAC5B2B,EAAA,KAAA1B,EAAkC,GAClC0B,EAAA,KAAAzB,GAA0B,GAC1ByB,EAAA,KAAAxB,GAA4B,IAC5BwB,EAAA,KAAAvB,GAAuB,KACvBuB,EAAA,KAAAtB,GAAsB,KA1exB,IAAAwB,EAAAC,EAAAC,EAAAC,EA6eI,KAAK,QAAUC,EAAA,CAAE,UAAW,IAASP,GACrCQ,GAAgB,KAAK,OAAO,EAC5BC,EAAA,KAAKxD,GAAckD,EAAA,KAAK,QAAQ,SAAb,KAAAA,EAAuB,MAC1CM,EAAA,KAAKvD,EAAmB,IACxBuD,EAAA,KAAKlD,EAAe,KAAK,QAAQ,QACjCkD,EAAA,KAAK5D,EAAiB,IAAI6D,GACxBV,EAAQ,OACRA,EAAQ,WACV,GACAS,EAAA,KAAK/C,GAAW,KAAK,QAAQ,SAC7B+C,EAAA,KAAKjD,GAAQ4C,EAAA,KAAK,QAAQ,MAAb,KAAAA,EAAoB,QAEjC,IAAMO,GACJN,EAAAL,EAAQ,cAAR,KAAAK,EACC,IAAIO,IAAmC,MAAM,GAAGA,CAAI,EAEjDC,EAAcC,GAAAP,EAAA,IACdD,EAAAN,EAAQ,iBAAR,KAAAM,EAA0BS,IADZ,CAElB,gBAAiB,IAAM,CA/f7B,IAAAZ,EAAAC,EAggBQK,EAAA,KAAKnD,EAAa,KAClB8C,GAAAD,EAAAH,EAAQ,iBAAR,YAAAG,EAAwB,kBAAxB,MAAAC,EAAA,KAAAD,EACF,CACF,GACMa,EAAyBC,GAC7BN,EACAE,CACF,EAEAJ,EAAA,KAAK7D,GAAkBsE,GACrBC,GAA2BH,CAAsB,CACnD,GAEAP,EAAA,KAAK9D,GAAeyE,GAAgCC,EAAA,KAAKzE,GAAe,GAExE0E,EAAA,KAAK1C,EAAAgB,IAAL,UACF,CAEA,IAAI,aAAc,CAChB,OAAOyB,EAAA,KAAK9D,EACd,CAEA,IAAI,OAAQ,CACV,OAAO8D,EAAA,KAAK3E,GACd,CAEA,IAAI,YAAa,CACf,OAAO2E,EAAA,KAAKjE,EACd,CAEA,IAAI,YAAa,CACf,OAAOiE,EAAA,KAAKpE,EACd,CAEA,IAAI,MAAO,CACT,OAAOoE,EAAA,KAAK7D,EACd,CAwfA,UACE+D,EACAC,EAAkC,IAAM,CAAC,EACzC,CACA,IAAMC,EAAiB,KAAK,OAAO,EAEnC,OAAAJ,EAAA,KAAKvE,GAAa,IAAI2E,EAAgB,CAACF,EAAUC,CAAO,CAAC,EACpDH,EAAA,KAAKtE,IAAUuE,EAAA,KAAK1C,EAAAC,IAAL,WAEb,IAAM,CACXwC,EAAA,KAAKvE,GAAa,OAAO2E,CAAc,CACzC,CACF,CAEA,gBAAuB,CACrBJ,EAAA,KAAKvE,GAAa,MAAM,CAC1B,CAGA,cAAmC,CACjC,OAAOuE,EAAA,KAAKlE,EACd,CAGA,YAAqB,CACnB,OAAIkE,EAAA,KAAKlE,KAAkB,OAAkB,IACtC,KAAK,IAAI,EAAIkE,EAAA,KAAKlE,EAC3B,CAGA,aAAuB,CACrB,OAAOkE,EAAA,KAAK/D,EACd,CAGA,WAAqB,CACnB,MAAO,CAAC+D,EAAA,KAAKjE,EACf,CAEA,YAAsB,CACpB,OAAOiE,EAAA,KAAKtE,EACd,CAEA,UAAoB,CAClB,OAAOsE,EAAA,KAAKrE,KAAW,QACzB,CA2CM,2BAA2C,QAAArB,EAAA,sBApnCnD,IAAAwE,EAAAC,EAqnCIK,EAAA,KAAK7C,EAAgB,IACjByD,EAAA,KAAKjE,IAAe,GAAC+C,EAAAkB,EAAA,KAAK1D,KAAL,MAAAwC,EAA8B,OAAO,YAG5DC,EAAAiB,EAAA,KAAK1D,KAAL,MAAAyC,EAA8B,MAAMsB,KAEtC,MAAMJ,EAAA,KAAK1C,EAAAY,IAAL,WACNiB,EAAA,KAAK7C,EAAgB,GACvB,GAgFM,gBAAgB+D,EAGnB,QAAAhG,EAAA,sBACD,GAAI0F,EAAA,KAAK7D,KAAU,OACjB,MAAM,IAAI,MACR,0CAA0C6D,EAAA,KAAK7D,EAAK,0DACtD,EAGG6D,EAAA,KAAKtE,KAAU,MAAMuE,EAAA,KAAK1C,EAAAC,IAAL,YAI1B,MAAMyC,EAAA,KAAK1C,EAAAa,IAAL,WAGNmC,GAAA,KAAK1D,GAAL,IAEA,GAAI,CACEmD,EAAA,KAAKnD,KAA4B,GAEnCoD,EAAA,KAAK1C,EAAAU,IAAL,WAGF,GAAM,CAAE,SAAAuC,EAAU,eAAAC,CAAe,EAAI,MAAMR,EAAA,KAAK1C,EAAAG,IAAL,UACzC,KAAK,QAAQ,IACb,GACA4C,GAGI,CAAE,SAAAI,EAAU,KAAAC,CAAK,EAAI,MAAMV,EAAA,KAAK1C,EAAAkB,IAAL,UAC/B+B,EACAC,GAGIG,EAAuBD,EAA2B,OAAO,CAC7D,CAAE,QAASzB,EAAA,CAAE,QAAS,gBAAmBwB,EAAW,CACtD,CAAC,EAED,OAAAV,EAAA,KAAKpD,IAAiB,YACpB8D,EACA,IAAI,IAAIC,EAAK,IAAKE,GAAYA,EAAQ,GAAG,CAAC,CAC5C,EACAZ,EAAA,KAAK1C,EAAAM,IAAL,UAAiB+C,EAAqB,IAE/B,CACL,SAAAF,EACA,KAAAC,CACF,CACF,QAAE,CAEAJ,GAAA,KAAK1D,GAAL,IACImD,EAAA,KAAKnD,KAA4B,GACnCoD,EAAA,KAAK1C,EAAAW,IAAL,UAEJ,CACF,GA0BF,EAh2BE7C,GAAA,YAESC,GAAA,YACAC,GAAA,YACAC,EAAA,YAEAC,EAAA,YAQTC,EAAA,YACAC,EAAA,YACAC,EAAA,YACAC,EAAA,YACAC,EAAA,YACAC,EAAA,YACAC,EAAA,YACAC,EAAA,YACAC,EAAA,YACAC,EAAA,YACAC,EAAA,YACAC,GAAA,YACAC,EAAA,YACAC,EAAA,YACAC,EAAA,YACAC,GAAA,YACAC,EAAA,YACAC,GAAA,YACAC,GAAA,YACAC,EAAA,YACAC,EAAA,YACAC,GAAA,YACAC,GAAA,YACAC,GAAA,YACAC,EAAA,YACAC,GAAA,YACAC,GAAA,YACAC,GAAA,YACAC,GAAA,YAnDKC,EAAA,YA+GCC,GAAM,UAAkB,QAAAlD,EAAA,sBAtiBhC,IAAAwE,EAAAC,EAAAC,EAAAC,EAAA6B,EAuiBI1B,EAAA,KAAK1D,EAAW,IAEhB,GAAI,CACF,MAAMuE,EAAA,KAAK1C,EAAAE,IAAL,UACR,OAASsD,EAAK,CAIZ,GAHA3B,EAAA,KAAK/D,GAAS0F,GAGVf,EAAA,KAAK3D,IAAU,CACjB,IAAM2E,EAAY,MAAMhB,EAAA,KAAK3D,IAAL,UAAc0E,GAEtC,GAAIC,GAAa,OAAOA,GAAc,SAAU,CAG1CA,EAAU,SAEZ,KAAK,QAAQ,OAAS9B,IAAA,IAChBJ,EAAA,KAAK,QAAQ,SAAb,KAAAA,EAAuB,CAAC,GACzBkC,EAAU,SAIbA,EAAU,UAEZ,KAAK,QAAQ,QAAU9B,IAAA,IACjBH,EAAA,KAAK,QAAQ,UAAb,KAAAA,EAAwB,CAAC,GAC1BiC,EAAU,UAKjB5B,EAAA,KAAK/D,GAAS,MAGd+D,EAAA,KAAK1D,EAAW,IAChB,MAAMuE,EAAA,KAAK1C,EAAAC,IAAL,WACN,MACF,CAGIuD,aAAe,OACjBd,EAAA,KAAK1C,EAAAe,IAAL,UAA6ByC,GAE/B3B,EAAA,KAAKnD,EAAa,KAClB+C,EAAAgB,EAAA,KAAKtD,KAAL,MAAAsC,EAAA,WACA,MACF,CAIA,MAAI+B,aAAe,OACjBd,EAAA,KAAK1C,EAAAe,IAAL,UAA6ByC,GAE/B3B,EAAA,KAAKnD,EAAa,KAClBgD,EAAAe,EAAA,KAAKtD,KAAL,MAAAuC,EAAA,WACM8B,CACR,CAGA3B,EAAA,KAAKnD,EAAa,KAClB6E,EAAAd,EAAA,KAAKtD,KAAL,MAAAoE,EAAA,UACF,IAEMrD,GAAa,UAAkB,QAAAnD,EAAA,sBAtmBvC,IAAAwE,EAAAC,EAumBI,GAAIiB,EAAA,KAAKrE,KAAW,kBAAmB,CACrCyD,EAAA,KAAKzD,EAAS,UAEd,MACF,CAEA,GACE,CAAC,KAAK,QAAQ,aACbmD,EAAA,KAAK,QAAQ,SAAb,MAAAA,EAAqB,SAAWkB,EAAA,KAAKjE,IAEtC,OAGF,IAAMkF,EAAoBjB,EAAA,KAAKrE,KAAW,SAC1CyD,EAAA,KAAKzD,EAAS,UAEd,GAAM,CAAE,IAAAT,EAAK,OAAAgG,CAAO,EAAI,KAAK,QACvB,CAAE,SAAAV,EAAU,eAAAC,CAAe,EAAI,MAAMR,EAAA,KAAK1C,EAAAG,IAAL,UACzCxC,EACA+F,GAEIE,EAAgB,MAAMlB,EAAA,KAAK1C,EAAAI,IAAL,UAA0BuD,GAChDE,EAAyBpB,EAAA,KAAK1D,GAEpC,GAAI,CACF,MAAM2D,EAAA,KAAK1C,EAAAO,IAAL,UAAiB,CACrB,SAAA0C,EACA,uBAAAY,EACA,QAASX,EACT,kBAAAQ,CACF,EACF,OAASI,EAAG,CAEV,IACGA,aAAaC,GAAcD,aAAaE,IACzCH,EAAuB,OAAO,SAC9BA,EAAuB,OAAO,SAAWf,GAGzC,OAAOJ,EAAA,KAAK1C,EAAAE,IAAL,WAGT,GAAI4D,aAAaE,EAAwB,CAErCH,EAAuB,OAAO,SAC9BA,EAAuB,OAAO,SAAWI,IAEzCpC,EAAA,KAAKzD,EAAS,UAEhB,MACF,CACA,GAAI,EAAE0F,aAAaC,GAAa,MAAMD,EAEtC,GAAIA,EAAE,QAAU,IAAK,CAOnB,GAAIrB,EAAA,KAAK9D,GAAc,CACrB,IAAMuF,EAAWxG,GAAkBuF,CAAQ,EAC3CkB,GAAmB,YAAYD,EAAUzB,EAAA,KAAK9D,EAAY,CAC5D,CAEA,IAAMyF,EACJN,EAAE,QAAQO,EAAmB,GAAK,GAAG5B,EAAA,KAAK9D,EAAa,QACzD,OAAA+D,EAAA,KAAK1C,EAAAiB,IAAL,UAAYmD,GAKZ,MAAM1B,EAAA,KAAK1C,EAAAc,IAAL,UACH,MAAM,QAAQgD,EAAE,IAAI,EAAIA,EAAE,KAAO,CAACA,EAAE,IAAI,GAEpCpB,EAAA,KAAK1C,EAAAE,IAAL,UACT,KAKE,OAAM4D,CAEV,QAAE,CACIF,GAAiBD,GACnBA,EAAO,oBAAoB,QAASC,CAAa,EAEnD/B,EAAA,KAAK9C,EAA0B,OACjC,CAEA,OAAAyC,EAAAiB,EAAA,KAAKvD,MAAL,MAAAsC,EAAA,WACOkB,EAAA,KAAK1C,EAAAE,IAAL,UACT,IAEMC,GAAa,SACjBxC,EACA+F,EACAY,EACA,QAAAvH,EAAA,sBAEA,GAAM,CAACmG,EAAgBjG,CAAM,EAAI,MAAM,QAAQ,IAAI,CACjDO,GAAe,KAAK,QAAQ,OAAO,EACnC,KAAK,QAAQ,OACTR,GAAiBuH,GAAwB,KAAK,QAAQ,MAAM,CAAC,EAC7D,MACN,CAAC,EAGGtH,GAAQuH,GAAevH,CAAM,EAEjC,IAAMgG,EAAW,IAAI,IAAItF,CAAG,EAG5B,GAAIV,EAAQ,CACNA,EAAO,OAAOwH,EAAcxB,EAAUyB,GAAmBzH,EAAO,KAAK,EACrEA,EAAO,OAAOwH,EAAcxB,EAAU0B,GAAmB1H,EAAO,KAAK,EACrEA,EAAO,SACTwH,EAAcxB,EAAU2B,GAAqB3H,EAAO,OAAO,EACzDA,EAAO,SAASwH,EAAcxB,EAAU4B,GAAe5H,EAAO,OAAO,EACrEA,EAAO,QACTwH,EAAcxB,EAAU6B,GAAoB7H,EAAO,MAAM,EAG3D,IAAM8H,EAAepD,EAAA,GAAK1E,GAC1B,OAAO8H,EAAa,MACpB,OAAOA,EAAa,MACpB,OAAOA,EAAa,QACpB,OAAOA,EAAa,QACpB,OAAOA,EAAa,OAEpB,OAAW,CAAC1H,EAAKP,CAAK,IAAK,OAAO,QAAQiI,CAAY,EACpDN,EAAcxB,EAAU5F,EAAKP,CAAK,CAEtC,CAEIwH,IACEA,EAAa,OACfG,EAAcxB,EAAU+B,GAAoBV,EAAa,KAAK,EAC5DA,EAAa,QACfG,EAAcxB,EAAUgC,GAA2BX,EAAa,MAAM,EACpEA,EAAa,OACfG,EAAcxB,EAAUiC,GAAoBZ,EAAa,KAAK,EAC5DA,EAAa,QACfG,EAAcxB,EAAUkC,GAAqBb,EAAa,MAAM,EAC9DA,EAAa,SACfG,EAAcxB,EAAUmC,GAAuBd,EAAa,OAAO,GAIvErB,EAAS,aAAa,IAAIrG,GAAoB6F,EAAA,KAAKpE,EAAW,EAC9D4E,EAAS,aAAa,IAAIoC,GAAsB5C,EAAA,KAAK7D,EAAK,EAEtD6D,EAAA,KAAKjE,KAIH,CAACiE,EAAA,KAAKzD,IAAiB,CAAC0E,GAC1BT,EAAS,aAAa,IAAItG,EAAkB,MAAM,EAEpDsG,EAAS,aAAa,IACpBxG,GACAgG,EAAA,KAAKnE,EACP,GAGEmE,EAAA,KAAK9D,IAEPsE,EAAS,aAAa,IAAIvG,GAA0B+F,EAAA,KAAK9D,EAAa,EAIxE,IAAMuF,EAAWxG,GAAkBuF,CAAQ,EACrCqC,EAAgBnB,GAAmB,iBAAiBD,CAAQ,EAClE,OAAIoB,GACFrC,EAAS,aAAa,IAAIsC,GAA4BD,CAAa,EAIrErC,EAAS,aAAa,KAAK,EAEpB,CACL,SAAAA,EACA,eAAAC,CACF,CACF,IAEM9C,GAAoB,SAACuD,EAAsB,QAAA5G,EAAA,sBAjyBnD,IAAAwE,EAsyBI,GAHAM,EAAA,KAAK9C,EAA0B,IAAI,iBAG/B4E,EAAQ,CACV,IAAMC,EAAgB,IAAM,CAvyBlC,IAAArC,GAwyBQA,EAAAkB,EAAA,KAAK1D,KAAL,MAAAwC,EAA8B,MAAMoC,EAAO,OAC7C,EAEA,OAAAA,EAAO,iBAAiB,QAASC,EAAe,CAAE,KAAM,EAAK,CAAC,EAE1DD,EAAO,WAETpC,EAAAkB,EAAA,KAAK1D,KAAL,MAAAwC,EAA8B,MAAMoC,EAAO,SAGtCC,CACT,CACF,IAEMvD,GAAkB,SAACmF,EAAoB,QAAAzI,EAAA,sBAtzB/C,IAAAwE,EAuzBI,GAAM,CAAE,QAAA9D,EAAS,OAAAgI,CAAO,EAAID,EACtBE,EAAcjI,EAAQ,IAAI4G,EAAmB,EAC/CqB,GACF7D,EAAA,KAAKlD,EAAe+G,GAGtB,IAAMC,EAAalI,EAAQ,IAAImI,EAAwB,EACnDD,GACF9D,EAAA,KAAKxD,EAAcsH,GAGrB,IAAME,EAAkBpI,EAAQ,IAAIqI,EAAwB,EACxDD,GACFhE,EAAA,KAAKvD,EAAmBuH,GAG1B,IAAME,EAAY,IAAc,CAC9B,IAAMC,EAAevI,EAAQ,IAAIwI,EAAmB,EACpD,OAAOD,EAAe,KAAK,MAAMA,CAAY,EAAI,CAAC,CACpD,EACAnE,EAAA,KAAKhD,GAAU0C,EAAAkB,EAAA,KAAK5D,KAAL,KAAA0C,EAAgBwE,EAAU,GAKrCN,IAAW,KAEb5D,EAAA,KAAKtD,EAAgB,KAAK,IAAI,EAElC,IAEM+B,GAAW,SAAC4F,EAA0BC,EAAe,GAAO,QAAApJ,EAAA,sBAt1BpE,IAAAwE,EAw1BI,GAAI2E,EAAM,OAAS,EAAG,CAEpBrE,EAAA,KAAKpD,EAAe,IAEpB,IAAM2H,EAAcF,EAAMA,EAAM,OAAS,CAAC,EAC1C,GAAIG,GAAkBD,CAAW,EAAG,CAClC,GAAID,EAAc,CAIhB,IAAMG,EAASC,GAAUH,CAAW,EAChCE,GACFzE,EAAA,KAAKxD,EAAciI,EAEvB,CACAzE,EAAA,KAAKtD,EAAgB,KAAK,IAAI,GAC9BsD,EAAA,KAAKrD,EAAc,IAEnBqD,EAAA,KAAKpD,EAAe,KAEpB8C,EAAAkB,EAAA,KAAKjD,MAAL,MAAA+B,EAAA,UACF,CAGA,IAAMiF,EAAoBN,EAAM,OAAQ5C,GAClCmD,GAAgBnD,CAAO,EAClB,CAACb,EAAA,KAAKpD,IAAiB,oBAAoBiE,CAAO,EAEpD,EACR,EAED,MAAMZ,EAAA,KAAK1C,EAAAc,IAAL,UAAc0F,EACtB,CACF,IASMjG,GAAW,SAACwC,EAKA,QAAAhG,EAAA,sBAv4BpB,IAAAwE,EAw4BI,IAAMmF,GAASnF,EAAA,KAAK,QAAQ,UAAb,KAAAA,EAAwB,KAAK,QAAQ,oBACpD,OACEkB,EAAA,KAAKjE,IACLkI,GACA,CAACjE,EAAA,KAAKzD,IACN,CAAC+D,EAAK,mBACN,CAACN,EAAA,KAAK5C,KAENkD,EAAK,SAAS,aAAa,IAAI4D,GAAmC,MAAM,EACxE5D,EAAK,SAAS,aAAa,IAAI6D,GAAsB,MAAM,EACpDlE,EAAA,KAAK1C,EAAAS,IAAL,UAAsBsC,IAGxBL,EAAA,KAAK1C,EAAAQ,IAAL,UAA2BuC,EACpC,IAEMvC,GAAqB,SAACuC,EAIV,QAAAhG,EAAA,sBAChB,GAAM,CAAE,SAAAkG,EAAU,uBAAAY,EAAwB,QAAApG,CAAQ,EAAIsF,EAChDyC,EAAW,MAAM/C,EAAA,KAAK1E,IAAL,UAAkBkF,EAAS,SAAS,EAAG,CAC5D,OAAQY,EAAuB,OAC/B,QAAApG,CACF,GAEAoE,EAAA,KAAKnD,EAAa,IAClB,MAAMgE,EAAA,KAAK1C,EAAAK,IAAL,UAAwBmF,GAE9B,IAAMqB,EAASpE,EAAA,KAAK5D,GAEdiI,GADM,MAAMtB,EAAS,KAAK,IACR,KAClBU,EAAQzD,EAAA,KAAKxE,GAAe,MAAyB6I,EAAUD,CAAM,EAE3E,MAAMnE,EAAA,KAAK1C,EAAAM,IAAL,UAAiB4F,EACzB,IAEMzF,GAAgB,SAACsC,EAIL,QAAAhG,EAAA,sBAChB,GAAM,CAAE,SAAAkG,EAAU,uBAAAY,EAAwB,QAAApG,CAAQ,EAAIsF,EAChDgE,EAAQtE,EAAA,KAAKzE,IAGnB6D,EAAA,KAAKpC,GAA8B,KAAK,IAAI,GAE5C,GAAI,CACF,IAAIuH,EAA4B,CAAC,EACjC,MAAMC,GAAiBhE,EAAS,SAAS,EAAG,CAC1C,QAAAxF,EACA,MAAAsJ,EACA,OAAevB,GAAuBzI,EAAA,sBACpC8E,EAAA,KAAKnD,EAAa,IAClB,MAAMgE,EAAA,KAAK1C,EAAAK,IAAL,UAAwBmF,EAChC,GACA,UAAY0B,GAA8B,CACxC,GAAIA,EAAM,KAAM,CAEd,IAAML,EAASpE,EAAA,KAAK5D,GACdyE,EAAUb,EAAA,KAAKxE,GAAe,MAClCiJ,EAAM,KACNL,CACF,EACAG,EAAO,KAAK1D,CAAO,EAEf+C,GAAkB/C,CAAO,IAG3BZ,EAAA,KAAK1C,EAAAM,IAAL,UAAiB0G,EAAQ,IACzBA,EAAS,CAAC,EAEd,CACF,EACA,QAAUG,GAAiB,CAEzB,MAAMA,CACR,EACA,OAAQtD,EAAuB,MACjC,CAAC,CACH,OAASsD,EAAO,CACd,MAAItD,EAAuB,OAAO,QAQ1B,IAAIG,EAENmD,CACR,QAAE,CAIA,IAAMC,EAAqB,KAAK,IAAI,EAAI3E,EAAA,KAAKhD,IACvC4H,EAAaxD,EAAuB,OAAO,QAEjD,GAAIuD,EAAqB3E,EAAA,KAAK/C,KAA6B,CAAC2H,EAI1D,GAFArE,GAAA,KAAKrD,GAAL,IAGE8C,EAAA,KAAK9C,IAAmC8C,EAAA,KAAK7C,IAG7CiC,EAAA,KAAKhC,GAA4B,IACjC,QAAQ,KACN,gbAKF,MACK,CAGL,IAAMyH,EAAW,KAAK,IACpB7E,EAAA,KAAK1C,IACL0C,EAAA,KAAK3C,IACH,KAAK,IAAI,EAAG2C,EAAA,KAAK9C,EAA+B,CACpD,EACM4H,EAAU,KAAK,MAAM,KAAK,OAAO,EAAID,CAAQ,EACnD,MAAM,IAAI,QAASE,GAAY,WAAWA,EAASD,CAAO,CAAC,CAC7D,MACSH,GAAsB3E,EAAA,KAAK/C,KAEpCmC,EAAA,KAAKlC,EAAkC,EAE3C,CACF,IAEAe,GAAM,UAAG,CA/gCX,IAAAa,EAghCQkB,EAAA,KAAKtE,IAAYsE,EAAA,KAAKrE,KAAW,WACnCyD,EAAA,KAAKzD,EAAS,oBACdmD,EAAAkB,EAAA,KAAK1D,KAAL,MAAAwC,EAA8B,MAAM0C,IAExC,EAEAtD,GAAO,UAAG,CACJ8B,EAAA,KAAKtE,IAAYsE,EAAA,KAAKrE,KAAW,UACnCsE,EAAA,KAAK1C,EAAAC,IAAL,UAEJ,EAkDMW,GAAS,UAAG,QAAA7D,EAAA,sBAChB,OAAI0F,EAAA,KAAKxD,GACAwD,EAAA,KAAKxD,IAEd4C,EAAA,KAAK5C,EAAe,IAAI,QAAQ,CAACuI,EAASC,IAAW,CACnD5F,EAAA,KAAK3C,GAAuBsI,GAC5B3F,EAAA,KAAK1C,EAAuBsI,EAC9B,CAAC,GACDhF,EAAA,KAAKxD,GAAa,QAAQ,IAAM,CAC9B4C,EAAA,KAAK5C,EAAe,QACpB4C,EAAA,KAAK3C,GAAuB,QAC5B2C,EAAA,KAAK1C,EAAuB,OAC9B,CAAC,EACMsD,EAAA,KAAKxD,GACd,IAGM4B,GAAiB,UAAG,QAAA9D,EAAA,sBACxB,GAAK0F,EAAA,KAAKhE,GAGV,OAAIgE,EAAA,KAAKlD,GACAkD,EAAA,KAAKlD,IAEdsC,EAAA,KAAKtC,EAAoB,IAAI,QAASiI,GAAY,CAChD3F,EAAA,KAAKrC,GAA4BgI,EACnC,CAAC,GACD/E,EAAA,KAAKlD,GAAkB,QAAQ,IAAM,CACnCsC,EAAA,KAAKtC,EAAoB,QACzBsC,EAAA,KAAKrC,GAA4B,OACnC,CAAC,EACMiD,EAAA,KAAKlD,GACd,IAmBMuB,GAAQ,SAACgG,EAAyC,QAAA/J,EAAA,sBAKtD,OAAA8E,EAAA,KAAKzC,GAAgBqD,EAAA,KAAKrD,IAAc,KAAK,IAC3C,QAAQ,IACN,MAAM,KAAKqD,EAAA,KAAKvE,GAAa,OAAO,CAAC,EAAE,IAAWd,GAAmBL,EAAA,MAAnBK,GAAmB,UAAnB,CAACuF,EAAU+E,CAAE,EAAM,CACnE,GAAI,CACF,MAAM/E,EAASmE,CAAQ,CACzB,OAAStD,EAAK,CACZ,eAAe,IAAM,CACnB,MAAMA,CACR,CAAC,CACH,CACF,EAAC,CACH,CACF,GAEOf,EAAA,KAAKrD,GACd,IAEA2B,GAAuB,SAACoG,EAAc,CACpC1E,EAAA,KAAKvE,GAAa,QAAQ,CAAC,CAACX,EAAGoK,CAAO,IAAM,CAC1CA,GAAA,MAAAA,EAAUR,EACZ,CAAC,CACH,EAEAnG,GAA6B,UAAG,CAC9B,GACE,OAAO,UAAa,UACpB,OAAO,SAAS,QAAW,WAC3B,OAAO,SAAS,kBAAqB,WACrC,CACA,IAAM4G,EAAoB,IAAM,CAC1B,SAAS,OACXlF,EAAA,KAAK1C,EAAAU,IAAL,WAEAgC,EAAA,KAAK1C,EAAAW,IAAL,UAEJ,EAEA,SAAS,iBAAiB,mBAAoBiH,CAAiB,CACjE,CACF,EAMA3G,GAAM,SAAC4G,EAAiB,CACtBhG,EAAA,KAAKxD,EAAc,MACnBwD,EAAA,KAAKvD,EAAmB,IACxBuD,EAAA,KAAKlD,EAAekJ,GACpBhG,EAAA,KAAKrD,EAAc,IACnBqD,EAAA,KAAKpD,EAAe,IACpBoD,EAAA,KAAKnD,EAAa,IAClBmD,EAAA,KAAKhD,EAAU,QACfgD,EAAA,KAAKvC,EAA0B,GAE/BuC,EAAA,KAAKlC,EAAkC,GACvCkC,EAAA,KAAKhC,GAA4B,GACnC,EA2EMqB,GAAc,SAACvD,EAAUF,EAAiC,QAAAV,EAAA,sBAC9D,IAAMyI,EAAW,MAAM/C,EAAA,KAAK1E,IAAL,UAAkBJ,EAAI,SAAS,EAAG,CAAE,QAAAF,CAAQ,GAEnE,GAAI,CAAC+H,EAAS,GACZ,MAAM,IAAIzB,EACRyB,EAAS,OACT,OACA,OACA,OAAO,YAAY,CAAC,GAAGA,EAAS,QAAQ,QAAQ,CAAC,CAAC,EAClD7H,EAAI,SAAS,CACf,EAGF,GAAM,CAAE,SAAAwF,EAAU,KAAAC,CAAK,EAAI,MAAMoC,EAAS,KAAK,EACzCU,EAAQzD,EAAA,KAAKxE,GAAe,MAChC,KAAK,UAAUmF,CAAI,EACnBX,EAAA,KAAK5D,EACP,EAEA,MAAO,CACL,SAAAsE,EACA,KAAM+C,CACR,CACF,IAx2BW/E,GAGK,QAAU,CACxB,KAAM,OACN,QAAS,SACX,EAy2BF,SAASqD,GAAevH,EAAmD,CACzE,GAAI,CAACA,EAAQ,OAEb,IAAM6K,EAAiB,OAAO,KAAK7K,CAAM,EAAE,OAAQI,GACjDb,GAAgB,IAAIa,CAAwB,CAC9C,EACA,GAAIyK,EAAe,OAAS,EAC1B,MAAM,IAAIC,GAAmBD,CAAc,CAE/C,CAEA,SAASlG,GAAmBR,EAA+C,CACzE,GAAI,CAACA,EAAQ,IACX,MAAM,IAAI4G,GAEZ,GAAI5G,EAAQ,QAAU,EAAEA,EAAQ,kBAAkB,aAChD,MAAM,IAAI6G,GAGZ,GACE7G,EAAQ,SAAW,QACnBA,EAAQ,SAAW,MACnBA,EAAQ,SAAW,OACnB,CAACA,EAAQ,OAET,MAAM,IAAI8G,GAGZ1D,GAAepD,EAAQ,MAAM,CAG/B,CAGA,SAASqD,EACP9G,EACAN,EACAP,EACM,CACN,GAAI,EAAAA,IAAU,QAAaA,GAAS,MAE7B,GAAI,OAAOA,GAAU,SAC1Ba,EAAI,aAAa,IAAIN,EAAKP,CAAK,UACtB,OAAOA,GAAU,SAC1B,OAAW,CAACqL,EAAGC,CAAC,IAAK,OAAO,QAAQtL,CAAK,EACvCa,EAAI,aAAa,IAAI,GAAGN,CAAG,IAAI8K,CAAC,IAAKC,CAAC,OAGxCzK,EAAI,aAAa,IAAIN,EAAKP,EAAM,SAAS,CAAC,CAE9C,CAEA,SAASyH,GACP8D,EAC2B,CAC3B,OAAI,MAAM,QAAQA,EAAY,MAAM,EAC3BnG,GAAAP,EAAA,GACF0G,GADE,CAEL,OAAQ,OAAO,YAAYA,EAAY,OAAO,IAAI,CAACD,EAAGE,IAAM,CAACA,EAAI,EAAGF,CAAC,CAAC,CAAC,CACzE,GAEKC,CACT,CGp2CA,IAAAE,EAAAC,EAAAC,EAAAC,GAAAC,GAAAC,GAAAC,EAAAC,EAAAC,GAAAC,GAAAC,GAAAC,GAAAC,GAAAC,GAiDaC,GAAN,KAA0C,CAW/C,YAAYC,EAAiC,CAXxCC,EAAA,KAAAT,GAGLS,EAAA,KAAShB,EAAsB,IAAI,KACnCgB,EAAA,KAASf,EAAe,IAAI,KAC5Be,EAAA,KAASd,EAAgB,IAAI,KAC7Bc,EAAA,KAASb,GAAyB,IAAI,KACtCa,EAAA,KAAAZ,GAA6B,IAC7BY,EAAA,KAAAX,GAAuB,WACvBW,EAAA,KAAAV,EAA6B,IAG3B,KAAK,OAASS,EACd,KAAK,OAAO,UACVE,EAAA,KAAKV,EAAAC,IAAS,KAAK,IAAI,EACvBS,EAAA,KAAKV,EAAAK,IAAa,KAAK,IAAI,CAC7B,CACF,CAEA,IAAI,YAAsB,CACxB,OAAOM,EAAA,KAAKb,MAAY,YAC1B,CAEA,IAAI,YAAqB,CACvB,OAAO,KAAK,OAAO,UACrB,CAEA,IAAI,QAA6B,CAC/B,OAAO,KAAK,OAAO,WACrB,CAEA,IAAI,MAAqB,CACvB,OAAO,KAAK,MAAM,KAAMc,GAAM,MAAM,KAAKA,EAAE,OAAO,CAAC,CAAC,CACtD,CAEA,IAAI,aAAmB,CACrB,OAAO,MAAM,KAAK,KAAK,aAAa,OAAO,CAAC,CAC9C,CAEA,IAAI,OAA+B,CACjC,OAAO,IAAI,QAAQ,CAACC,EAASC,IAAW,CACtC,GAAI,KAAK,OAAO,WACdD,EAAQ,KAAK,YAAY,MACpB,CACL,IAAME,EAAc,KAAK,UAAU,CAAC,CAAE,MAAAC,CAAM,IAAM,CAChDD,EAAY,EACRJ,EAAA,KAAKZ,IAAQe,EAAOH,EAAA,KAAKZ,EAAM,EACnCc,EAAQG,CAAK,CACf,CAAC,CACH,CACF,CAAC,CACH,CAEA,IAAI,cAAe,CACjB,OAAOL,EAAA,KAAKlB,EACd,CAEA,IAAI,OAAQ,CACV,OAAOkB,EAAA,KAAKZ,EACd,CAGA,cAAmC,CACjC,OAAO,KAAK,OAAO,aAAa,CAClC,CAGA,YAAa,CACX,OAAO,KAAK,OAAO,WAAW,CAChC,CAGA,WAAY,CACV,OAAO,KAAK,OAAO,UAAU,CAC/B,CAGA,aAAuB,CACrB,OAAO,KAAK,OAAO,YAAY,CACjC,CAGA,IAAI,MAAgB,CAClB,OAAO,KAAK,OAAO,IACrB,CAMM,gBACJkB,EACe,QAAAC,EAAA,sBAEf,IAAMC,EAAM,KAAK,UAAUF,CAAM,EACjCN,EAAA,KAAKf,IAAuB,IAAIuB,CAAG,EAEnC,MAAMT,EAAA,KAAKV,EAAAG,IAAL,WACN,MAAM,KAAK,OAAO,gBAAgBc,CAAM,CAC1C,GAEA,UAAUG,EAA+C,CACvD,IAAMC,EAAiB,KAAK,OAAO,EAEnC,OAAAV,EAAA,KAAKjB,GAAa,IAAI2B,EAAgBD,CAAQ,EAEvC,IAAM,CACXT,EAAA,KAAKjB,GAAa,OAAO2B,CAAc,CACzC,CACF,CAEA,gBAAuB,CACrBV,EAAA,KAAKjB,GAAa,MAAM,CAC1B,CAEA,IAAI,gBAAiB,CACnB,OAAOiB,EAAA,KAAKjB,GAAa,IAC3B,CA8HF,EAhPWD,EAAA,YACAC,EAAA,YACAC,EAAA,YACAC,GAAA,YACTC,GAAA,YACAC,GAAA,YACAC,EAAA,YATKC,EAAA,YAuHLC,GAAQ,SAACqB,EAA8B,CACrC,IAAIC,EAAe,GAEnBD,EAAS,QAASE,GAAY,CAC5B,GAAIC,GAAgBD,CAAO,EAEzB,GADAD,EAAeb,EAAA,KAAKV,EAAAI,IAAL,UAAwB,WACnC,KAAK,OAAS,OAChB,OAAQoB,EAAQ,QAAQ,UAAW,CACjC,IAAK,SACHb,EAAA,KAAKlB,GAAM,IAAI+B,EAAQ,IAAKA,EAAQ,KAAK,EACzC,MACF,IAAK,SACHb,EAAA,KAAKlB,GAAM,IAAI+B,EAAQ,IAAKE,IAAA,GACvBf,EAAA,KAAKlB,GAAM,IAAI+B,EAAQ,GAAG,GAC1BA,EAAQ,MACZ,EACD,MACF,IAAK,SACHb,EAAA,KAAKlB,GAAM,OAAO+B,EAAQ,GAAG,EAC7B,KACJ,KAGA,QAAQA,EAAQ,QAAQ,UAAW,CACjC,IAAK,SACHb,EAAA,KAAKhB,GAAc,IAAI6B,EAAQ,GAAG,EAClCb,EAAA,KAAKlB,GAAM,IAAI+B,EAAQ,IAAKA,EAAQ,KAAK,EACzC,MACF,IAAK,SACCb,EAAA,KAAKhB,GAAc,IAAI6B,EAAQ,GAAG,GACpCb,EAAA,KAAKlB,GAAM,IAAI+B,EAAQ,IAAKE,IAAA,GACvBf,EAAA,KAAKlB,GAAM,IAAI+B,EAAQ,GAAG,GAC1BA,EAAQ,MACZ,EAEH,MACF,IAAK,SACCb,EAAA,KAAKhB,GAAc,IAAI6B,EAAQ,GAAG,IACpCb,EAAA,KAAKlB,GAAM,OAAO+B,EAAQ,GAAG,EAC7Bb,EAAA,KAAKhB,GAAc,OAAO6B,EAAQ,GAAG,GAEvC,KACJ,CAIJ,GAAIG,GAAiBH,CAAO,EAC1B,OAAQA,EAAQ,QAAQ,QAAS,CAC/B,IAAK,aACHD,EAAeb,EAAA,KAAKV,EAAAI,IAAL,UAAwB,cACnCO,EAAA,KAAKd,MACP+B,EAAA,KAAK/B,GAA6B,IAC7Ba,EAAA,KAAKV,EAAAE,IAAL,YAEP,MACF,IAAK,eACHS,EAAA,KAAKlB,GAAM,MAAM,EACjBkB,EAAA,KAAKhB,GAAc,MAAM,EACzBiC,EAAA,KAAK7B,EAAS,IACdwB,EAAeb,EAAA,KAAKV,EAAAI,IAAL,UAAwB,WAEvCwB,EAAA,KAAK/B,GAA6B,IAClC,KACJ,CAEJ,CAAC,EAEG0B,GAAcb,EAAA,KAAKV,EAAAM,IAAL,UACpB,EAEMJ,GAAmB,UAAkB,QAAAgB,EAAA,sBAEzC,MAAMR,EAAA,KAAKV,EAAAG,IAAL,WAGN,MAAM,QAAQ,IACZ,MAAM,KAAKQ,EAAA,KAAKf,GAAsB,EAAE,IAAWiC,GAAeX,EAAA,sBAChE,GAAI,CACF,IAAMY,EAAW,KAAK,MAAMD,CAAU,EACtC,MAAM,KAAK,OAAO,gBAAgBC,CAAQ,CAC5C,OAASC,EAAG,CAEZ,CACF,EAAC,CACH,CACF,IAEM5B,GAAc,UAAkB,QAAAe,EAAA,sBAChC,KAAK,OAAO,aAChB,MAAM,IAAI,QAAeL,GAAY,CACnC,IAAMmB,EAAQ,IAAM,CACd,KAAK,OAAO,aACd,cAAcC,CAAQ,EACtBC,EAAM,EACNrB,EAAQ,EAEZ,EACMoB,EAAW,YAAYD,EAAO,EAAE,EAChCE,EAAQ,KAAK,OAAO,UACxB,IAAMF,EAAM,EACZ,IAAMA,EAAM,CACd,EACAA,EAAM,CACR,CAAC,EACH,IAEA5B,GAAkB,SAAC+B,EAA8B,CAC/C,IAAMC,EAAezB,EAAA,KAAKb,MAAYqC,EACtC,OAAAP,EAAA,KAAK9B,GAAUqC,GACRC,GAAgBD,IAAW,YACpC,EAEA9B,GAAY,SAAC,EAAgB,CACvB,aAAagC,IACfT,EAAA,KAAK7B,EAAS,GACdW,EAAA,KAAKV,EAAAM,IAAL,WAEJ,EAEAA,GAAO,UAAS,CACdK,EAAA,KAAKjB,GAAa,QAAS0B,GAAa,CACtCA,EAAS,CAAE,MAAO,KAAK,aAAc,KAAM,KAAK,WAAY,CAAC,CAC/D,CAAC,CACH","names":["FetchError","_FetchError","status","text","json","headers","url","message","response","__async","contentType","FetchBackoffAbortError","MissingShapeUrlError","InvalidSignalError","MissingShapeHandleError","ReservedParamError","reservedParams","ParserNullValueError","columnName","MissingHeadersError","url","missingHeaders","msg","h","parseNumber","value","parseBool","parseBigInt","parseJson","identityParser","v","defaultParser","pgArrayParser","parser","i","char","str","quoted","last","p","extractValue","x","start","end","val","loop","xs","MessageParser","transformer","__spreadValues","messages","schema","key","row","_b","columnInfo","_a","typ","dimensions","additionalInfo","__objRest","typeParser","makeNullableParser","_","columnName","isNullable","ParserNullValueError","isChangeMessage","message","isControlMessage","isUpToDateMessage","getOffset","lsn","isVisibleInSnapshot","txid","snapshot","xid","xmin","xmax","xip","LIVE_CACHE_BUSTER_HEADER","SHAPE_HANDLE_HEADER","CHUNK_LAST_OFFSET_HEADER","SHAPE_SCHEMA_HEADER","CHUNK_UP_TO_DATE_HEADER","COLUMNS_QUERY_PARAM","LIVE_CACHE_BUSTER_QUERY_PARAM","EXPIRED_HANDLE_QUERY_PARAM","SHAPE_HANDLE_QUERY_PARAM","LIVE_QUERY_PARAM","OFFSET_QUERY_PARAM","TABLE_QUERY_PARAM","WHERE_QUERY_PARAM","REPLICA_PARAM","WHERE_PARAMS_PARAM","EXPERIMENTAL_LIVE_SSE_QUERY_PARAM","LIVE_SSE_QUERY_PARAM","FORCE_DISCONNECT_AND_REFRESH","PAUSE_STREAM","LOG_MODE_QUERY_PARAM","SUBSET_PARAM_WHERE","SUBSET_PARAM_LIMIT","SUBSET_PARAM_OFFSET","SUBSET_PARAM_ORDER_BY","SUBSET_PARAM_WHERE_PARAMS","ELECTRIC_PROTOCOL_QUERY_PARAMS","HTTP_RETRY_STATUS_CODES","BackoffDefaults","parseRetryAfterHeader","retryAfter","retryAfterSec","retryDate","deltaMs","createFetchWithBackoff","fetchClient","backoffOptions","initialDelay","maxDelay","multiplier","debug","onFailedAttempt","maxRetries","args","__async","_a","url","options","delay","attempt","result","FetchError","e","FetchBackoffAbortError","serverMinimumMs","jitter","clientBackoffMs","waitMs","source","resolve","NO_BODY_STATUS_CODES","createFetchWithConsumedMessages","_b","res","text","err","ChunkPrefetchDefaults","createFetchWithChunkBuffer","prefetchOptions","maxChunksToPrefetch","prefetchQueue","prefetchedRequest","response","nextUrl","getNextChunkUrl","PrefetchQueue","requiredElectricResponseHeaders","requiredLiveResponseHeaders","requiredNonLiveResponseHeaders","createFetchWithResponseHeadersCheck","headers","missingHeaders","addMissingHeaders","requiredHeaders","h","urlString","SUBSET_PARAM_WHERE","SUBSET_PARAM_WHERE_PARAMS","SUBSET_PARAM_LIMIT","SUBSET_PARAM_OFFSET","SUBSET_PARAM_ORDER_BY","p","LIVE_QUERY_PARAM","MissingHeadersError","_fetchClient","_maxPrefetchedRequests","_prefetchQueue","_queueHeadUrl","_queueTailUrl","_PrefetchQueue_instances","prefetch_fn","__privateAdd","__privateSet","__privateGet","__privateMethod","_","aborter","request","signal","cleanup","chainAborter","__spreadProps","__spreadValues","shapeHandle","SHAPE_HANDLE_HEADER","lastOffset","CHUNK_LAST_OFFSET_HEADER","isUpToDate","CHUNK_UP_TO_DATE_HEADER","SHAPE_HANDLE_QUERY_PARAM","OFFSET_QUERY_PARAM","sourceSignal","noop","abortParent","fetchEventSource","ExpiredShapesCache","shapeUrl","entry","handle","keys","oldest","min","k","stored","expiredShapesCache","SnapshotTracker","metadata","keys","_a","_b","_c","_d","xmaxSet","databaseLsnSet","snapshotMark","message","txids","xid","xmax","snapshots","snapshot","x","isVisibleInSnapshot","newDatabaseLsn","dbLsn","RESERVED_PARAMS","LIVE_CACHE_BUSTER_QUERY_PARAM","SHAPE_HANDLE_QUERY_PARAM","LIVE_QUERY_PARAM","OFFSET_QUERY_PARAM","resolveValue","value","__async","toInternalParams","params","entries","resolvedEntries","_0","key","resolvedValue","_","resolveHeaders","headers","canonicalShapeKey","url","cleanUrl","ELECTRIC_PROTOCOL_QUERY_PARAMS","_error","_fetchClient","_sseFetchClient","_messageParser","_subscribers","_started","_state","_lastOffset","_liveCacheBuster","_lastSyncedAt","_isUpToDate","_isMidStream","_connected","_shapeHandle","_mode","_schema","_onError","_requestAbortController","_isRefreshing","_tickPromise","_tickPromiseResolver","_tickPromiseRejecter","_messageChain","_snapshotTracker","_activeSnapshotRequests","_midStreamPromise","_midStreamPromiseResolver","_lastSseConnectionStartTime","_minSseConnectionDuration","_consecutiveShortSseConnections","_maxShortSseConnections","_sseFallbackToLongPolling","_sseBackoffBaseDelay","_sseBackoffMaxDelay","_ShapeStream_instances","start_fn","requestShape_fn","constructUrl_fn","createAbortListener_fn","onInitialResponse_fn","onMessages_fn","fetchShape_fn","requestShapeLongPoll_fn","requestShapeSSE_fn","pause_fn","resume_fn","nextTick_fn","waitForStreamEnd_fn","publish_fn","sendErrorToSubscribers_fn","subscribeToVisibilityChanges_fn","reset_fn","fetchSnapshot_fn","ShapeStream","options","__privateAdd","SnapshotTracker","_a","_b","_c","_d","__spreadValues","validateOptions","__privateSet","MessageParser","baseFetchClient","args","backOffOpts","__spreadProps","BackoffDefaults","fetchWithBackoffClient","createFetchWithBackoff","createFetchWithResponseHeadersCheck","createFetchWithChunkBuffer","createFetchWithConsumedMessages","__privateGet","__privateMethod","callback","onError","subscriptionId","FORCE_DISCONNECT_AND_REFRESH","opts","__privateWrapper","fetchUrl","requestHeaders","metadata","data","dataWithEndBoundary","message","_e","err","retryOpts","resumingFromPause","signal","abortListener","requestAbortController","e","FetchError","FetchBackoffAbortError","PAUSE_STREAM","shapeKey","expiredShapesCache","newShapeHandle","SHAPE_HANDLE_HEADER","subsetParams","convertWhereParamsToObj","validateParams","setQueryParam","TABLE_QUERY_PARAM","WHERE_QUERY_PARAM","COLUMNS_QUERY_PARAM","REPLICA_PARAM","WHERE_PARAMS_PARAM","customParams","SUBSET_PARAM_WHERE","SUBSET_PARAM_WHERE_PARAMS","SUBSET_PARAM_LIMIT","SUBSET_PARAM_OFFSET","SUBSET_PARAM_ORDER_BY","LOG_MODE_QUERY_PARAM","expiredHandle","EXPIRED_HANDLE_QUERY_PARAM","response","status","shapeHandle","lastOffset","CHUNK_LAST_OFFSET_HEADER","liveCacheBuster","LIVE_CACHE_BUSTER_HEADER","getSchema","schemaHeader","SHAPE_SCHEMA_HEADER","batch","isSseMessage","lastMessage","isUpToDateMessage","offset","getOffset","messagesToProcess","isChangeMessage","useSse","EXPERIMENTAL_LIVE_SSE_QUERY_PARAM","LIVE_SSE_QUERY_PARAM","schema","messages","fetch","buffer","fetchEventSource","event","error","connectionDuration","wasAborted","maxDelay","delayMs","resolve","reject","__","errorFn","visibilityHandler","handle","reservedParams","ReservedParamError","MissingShapeUrlError","InvalidSignalError","MissingShapeHandleError","k","v","allPgParams","i","_data","_subscribers","_insertedKeys","_requestedSubSnapshots","_reexecuteSnapshotsPending","_status","_error","_Shape_instances","process_fn","reexecuteSnapshots_fn","awaitUpToDate_fn","updateShapeStatus_fn","handleError_fn","notify_fn","Shape","stream","__privateAdd","__privateMethod","__privateGet","v","resolve","reject","unsubscribe","value","params","__async","key","callback","subscriptionId","messages","shouldNotify","message","isChangeMessage","__spreadValues","isControlMessage","__privateSet","jsonParams","snapshot","_","check","interval","unsub","status","stateChanged","FetchError"]}