{"version":3,"file":"firebase-data-connect.js","sources":["../util/src/errors.ts","../util/src/url.ts","../component/src/component.ts","../logger/src/logger.ts","../data-connect/src/core/version.ts","../data-connect/src/core/error.ts","../data-connect/src/cache/EntityDataObject.ts","../data-connect/src/cache/InMemoryCacheProvider.ts","../data-connect/src/cache/EntityNode.ts","../data-connect/src/cache/ResultTree.ts","../data-connect/src/cache/ImpactedQueryRefsAccumulator.ts","../data-connect/src/cache/ResultTreeProcessor.ts","../data-connect/src/cache/Cache.ts","../util/src/sha256.ts","../data-connect/src/core/AppCheckTokenProvider.ts","../data-connect/src/logger.ts","../data-connect/src/core/FirebaseAuthProvider.ts","../data-connect/src/api/Reference.ts","../data-connect/src/cache/cacheUtils.ts","../data-connect/src/util/encoder.ts","../data-connect/src/core/query/QueryManager.ts","../data-connect/src/network/transport.ts","../data-connect/src/network/rest/fetch.ts","../data-connect/src/util/url.ts","../data-connect/src/network/rest/restTransport.ts","../data-connect/src/network/stream/streamTransport.ts","../data-connect/src/network/stream/websocket.ts","../data-connect/src/network/manager.ts","../data-connect/src/api/Mutation.ts","../data-connect/src/api/DataConnect.ts","../data-connect/src/core/query/queryOptions.ts","../data-connect/src/api/query.ts","../data-connect/src/util/validateArgs.ts","../data-connect/src/core/query/subscribe.ts","../data-connect/src/register.ts","../data-connect/src/index.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2017 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * @fileoverview Standardized Firebase Error.\n *\n * Usage:\n *\n *   // TypeScript string literals for type-safe codes\n *   type Err =\n *     'unknown' |\n *     'object-not-found'\n *     ;\n *\n *   // Closure enum for type-safe error codes\n *   // at-enum {string}\n *   var Err = {\n *     UNKNOWN: 'unknown',\n *     OBJECT_NOT_FOUND: 'object-not-found',\n *   }\n *\n *   let errors: Map<Err, string> = {\n *     'generic-error': \"Unknown error\",\n *     'file-not-found': \"Could not find file: {$file}\",\n *   };\n *\n *   // Type-safe function - must pass a valid error code as param.\n *   let error = new ErrorFactory<Err>('service', 'Service', errors);\n *\n *   ...\n *   throw error.create(Err.GENERIC);\n *   ...\n *   throw error.create(Err.FILE_NOT_FOUND, {'file': fileName});\n *   ...\n *   // Service: Could not file file: foo.txt (service/file-not-found).\n *\n *   catch (e) {\n *     assert(e.message === \"Could not find file: foo.txt.\");\n *     if ((e as FirebaseError)?.code === 'service/file-not-found') {\n *       console.log(\"Could not read file: \" + e['file']);\n *     }\n *   }\n */\n\nexport type ErrorMap<ErrorCode extends string> = {\n  readonly [K in ErrorCode]: string;\n};\n\nconst ERROR_NAME = 'FirebaseError';\n\nexport interface StringLike {\n  toString(): string;\n}\n\nexport interface ErrorData {\n  [key: string]: unknown;\n}\n\n// Based on code from:\n// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error#Custom_Error_Types\nexport class FirebaseError extends Error {\n  /** The custom name for all FirebaseErrors. */\n  readonly name: string = ERROR_NAME;\n\n  constructor(\n    /** The error code for this error. */\n    readonly code: string,\n    message: string,\n    /** Custom data for this error. */\n    public customData?: Record<string, unknown>\n  ) {\n    super(message);\n\n    // Fix For ES5\n    // https://github.com/Microsoft/TypeScript-wiki/blob/master/Breaking-Changes.md#extending-built-ins-like-error-array-and-map-may-no-longer-work\n    // TODO(dlarocque): Replace this with `new.target`: https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-2.html#support-for-newtarget\n    //                   which we can now use since we no longer target ES5.\n    Object.setPrototypeOf(this, FirebaseError.prototype);\n\n    // Maintains proper stack trace for where our error was thrown.\n    // Only available on V8.\n    if (Error.captureStackTrace) {\n      Error.captureStackTrace(this, ErrorFactory.prototype.create);\n    }\n  }\n}\n\nexport class ErrorFactory<\n  ErrorCode extends string,\n  ErrorParams extends { readonly [K in ErrorCode]?: ErrorData } = {}\n> {\n  constructor(\n    private readonly service: string,\n    private readonly serviceName: string,\n    private readonly errors: ErrorMap<ErrorCode>\n  ) {}\n\n  create<K extends ErrorCode>(\n    code: K,\n    ...data: K extends keyof ErrorParams ? [ErrorParams[K]] : []\n  ): FirebaseError {\n    const customData = (data[0] as ErrorData) || {};\n    const fullCode = `${this.service}/${code}`;\n    const template = this.errors[code];\n\n    const message = template ? replaceTemplate(template, customData) : 'Error';\n    // Service Name: Error message (service/code).\n    const fullMessage = `${this.serviceName}: ${message} (${fullCode}).`;\n\n    const error = new FirebaseError(fullCode, fullMessage, customData);\n\n    return error;\n  }\n}\n\nfunction replaceTemplate(template: string, data: ErrorData): string {\n  return template.replace(PATTERN, (_, key) => {\n    const value = data[key];\n    return value != null ? String(value) : `<${key}?>`;\n  });\n}\n\nconst PATTERN = /\\{\\$([^}]+)}/g;\n","/**\n * @license\n * Copyright 2025 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Checks whether host is a cloud workstation or not.\n * @public\n */\nexport function isCloudWorkstation(url: string): boolean {\n  // `isCloudWorkstation` is called without protocol in certain connect*Emulator functions\n  // In HTTP request builders, it's called with the protocol.\n  // If called with protocol prefix, it's a valid URL, so we extract the hostname\n  // If called without, we assume the string is the hostname.\n  try {\n    const host =\n      url.startsWith('http://') || url.startsWith('https://')\n        ? new URL(url).hostname\n        : url;\n    return host.endsWith('.cloudworkstations.dev');\n  } catch {\n    return false;\n  }\n}\n\n/**\n * Makes a fetch request to the given server.\n * Mostly used for forwarding cookies in Firebase Studio.\n * @public\n */\nexport async function pingServer(endpoint: string): Promise<boolean> {\n  const result = await fetch(endpoint, {\n    credentials: 'include'\n  });\n  return result.ok;\n}\n","/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport {\n  InstantiationMode,\n  InstanceFactory,\n  ComponentType,\n  Dictionary,\n  Name,\n  onInstanceCreatedCallback\n} from './types';\n\n/**\n * Component for service name T, e.g. `auth`, `auth-internal`\n */\nexport class Component<T extends Name = Name> {\n  multipleInstances = false;\n  /**\n   * Properties to be added to the service namespace\n   */\n  serviceProps: Dictionary = {};\n\n  instantiationMode = InstantiationMode.LAZY;\n\n  onInstanceCreated: onInstanceCreatedCallback<T> | null = null;\n\n  /**\n   *\n   * @param name The public service name, e.g. app, auth, firestore, database\n   * @param instanceFactory Service factory responsible for creating the public interface\n   * @param type whether the service provided by the component is public or private\n   */\n  constructor(\n    readonly name: T,\n    readonly instanceFactory: InstanceFactory<T>,\n    readonly type: ComponentType\n  ) {}\n\n  setInstantiationMode(mode: InstantiationMode): this {\n    this.instantiationMode = mode;\n    return this;\n  }\n\n  setMultipleInstances(multipleInstances: boolean): this {\n    this.multipleInstances = multipleInstances;\n    return this;\n  }\n\n  setServiceProps(props: Dictionary): this {\n    this.serviceProps = props;\n    return this;\n  }\n\n  setInstanceCreatedCallback(callback: onInstanceCreatedCallback<T>): this {\n    this.onInstanceCreated = callback;\n    return this;\n  }\n}\n","/**\n * @license\n * Copyright 2017 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport type LogLevelString =\n  | 'debug'\n  | 'verbose'\n  | 'info'\n  | 'warn'\n  | 'error'\n  | 'silent';\n\nexport interface LogOptions {\n  level: LogLevelString;\n}\n\nexport type LogCallback = (callbackParams: LogCallbackParams) => void;\n\nexport interface LogCallbackParams {\n  level: LogLevelString;\n  message: string;\n  args: unknown[];\n  type: string;\n}\n\n/**\n * A container for all of the Logger instances\n */\nexport const instances: Logger[] = [];\n\n/**\n * The JS SDK supports 5 log levels and also allows a user the ability to\n * silence the logs altogether.\n *\n * The order is a follows:\n * DEBUG < VERBOSE < INFO < WARN < ERROR\n *\n * All of the log types above the current log level will be captured (i.e. if\n * you set the log level to `INFO`, errors will still be logged, but `DEBUG` and\n * `VERBOSE` logs will not)\n */\nexport enum LogLevel {\n  DEBUG,\n  VERBOSE,\n  INFO,\n  WARN,\n  ERROR,\n  SILENT\n}\n\nconst levelStringToEnum: { [key in LogLevelString]: LogLevel } = {\n  'debug': LogLevel.DEBUG,\n  'verbose': LogLevel.VERBOSE,\n  'info': LogLevel.INFO,\n  'warn': LogLevel.WARN,\n  'error': LogLevel.ERROR,\n  'silent': LogLevel.SILENT\n};\n\n/**\n * The default log level\n */\nconst defaultLogLevel: LogLevel = LogLevel.INFO;\n\n/**\n * We allow users the ability to pass their own log handler. We will pass the\n * type of log, the current log level, and any other arguments passed (i.e. the\n * messages that the user wants to log) to this function.\n */\nexport type LogHandler = (\n  loggerInstance: Logger,\n  logType: LogLevel,\n  ...args: unknown[]\n) => void;\n\n/**\n * By default, `console.debug` is not displayed in the developer console (in\n * chrome). To avoid forcing users to have to opt-in to these logs twice\n * (i.e. once for firebase, and once in the console), we are sending `DEBUG`\n * logs to the `console.log` function.\n */\nconst ConsoleMethod = {\n  [LogLevel.DEBUG]: 'log',\n  [LogLevel.VERBOSE]: 'log',\n  [LogLevel.INFO]: 'info',\n  [LogLevel.WARN]: 'warn',\n  [LogLevel.ERROR]: 'error'\n};\n\n/**\n * The default log handler will forward DEBUG, VERBOSE, INFO, WARN, and ERROR\n * messages on to their corresponding console counterparts (if the log method\n * is supported by the current log level)\n */\nconst defaultLogHandler: LogHandler = (instance, logType, ...args): void => {\n  if (logType < instance.logLevel) {\n    return;\n  }\n  const now = new Date().toISOString();\n  const method = ConsoleMethod[logType as keyof typeof ConsoleMethod];\n  if (method) {\n    console[method as 'log' | 'info' | 'warn' | 'error'](\n      `[${now}]  ${instance.name}:`,\n      ...args\n    );\n  } else {\n    throw new Error(\n      `Attempted to log a message with an invalid logType (value: ${logType})`\n    );\n  }\n};\n\nexport class Logger {\n  /**\n   * Gives you an instance of a Logger to capture messages according to\n   * Firebase's logging scheme.\n   *\n   * @param name The name that the logs will be associated with\n   */\n  constructor(public name: string) {\n    /**\n     * Capture the current instance for later use\n     */\n    instances.push(this);\n  }\n\n  /**\n   * The log level of the given Logger instance.\n   */\n  private _logLevel = defaultLogLevel;\n\n  get logLevel(): LogLevel {\n    return this._logLevel;\n  }\n\n  set logLevel(val: LogLevel) {\n    if (!(val in LogLevel)) {\n      throw new TypeError(`Invalid value \"${val}\" assigned to \\`logLevel\\``);\n    }\n    this._logLevel = val;\n  }\n\n  // Workaround for setter/getter having to be the same type.\n  setLogLevel(val: LogLevel | LogLevelString): void {\n    this._logLevel = typeof val === 'string' ? levelStringToEnum[val] : val;\n  }\n\n  /**\n   * The main (internal) log handler for the Logger instance.\n   * Can be set to a new function in internal package code but not by user.\n   */\n  private _logHandler: LogHandler = defaultLogHandler;\n  get logHandler(): LogHandler {\n    return this._logHandler;\n  }\n  set logHandler(val: LogHandler) {\n    if (typeof val !== 'function') {\n      throw new TypeError('Value assigned to `logHandler` must be a function');\n    }\n    this._logHandler = val;\n  }\n\n  /**\n   * The optional, additional, user-defined log handler for the Logger instance.\n   */\n  private _userLogHandler: LogHandler | null = null;\n  get userLogHandler(): LogHandler | null {\n    return this._userLogHandler;\n  }\n  set userLogHandler(val: LogHandler | null) {\n    this._userLogHandler = val;\n  }\n\n  /**\n   * The functions below are all based on the `console` interface\n   */\n\n  debug(...args: unknown[]): void {\n    this._userLogHandler && this._userLogHandler(this, LogLevel.DEBUG, ...args);\n    this._logHandler(this, LogLevel.DEBUG, ...args);\n  }\n  log(...args: unknown[]): void {\n    this._userLogHandler &&\n      this._userLogHandler(this, LogLevel.VERBOSE, ...args);\n    this._logHandler(this, LogLevel.VERBOSE, ...args);\n  }\n  info(...args: unknown[]): void {\n    this._userLogHandler && this._userLogHandler(this, LogLevel.INFO, ...args);\n    this._logHandler(this, LogLevel.INFO, ...args);\n  }\n  warn(...args: unknown[]): void {\n    this._userLogHandler && this._userLogHandler(this, LogLevel.WARN, ...args);\n    this._logHandler(this, LogLevel.WARN, ...args);\n  }\n  error(...args: unknown[]): void {\n    this._userLogHandler && this._userLogHandler(this, LogLevel.ERROR, ...args);\n    this._logHandler(this, LogLevel.ERROR, ...args);\n  }\n}\n\nexport function setLogLevel(level: LogLevelString | LogLevel): void {\n  instances.forEach(inst => {\n    inst.setLogLevel(level);\n  });\n}\n\nexport function setUserLogHandler(\n  logCallback: LogCallback | null,\n  options?: LogOptions\n): void {\n  for (const instance of instances) {\n    let customLogLevel: LogLevel | null = null;\n    if (options && options.level) {\n      customLogLevel = levelStringToEnum[options.level];\n    }\n    if (logCallback === null) {\n      instance.userLogHandler = null;\n    } else {\n      instance.userLogHandler = (\n        instance: Logger,\n        level: LogLevel,\n        ...args: unknown[]\n      ) => {\n        const message = args\n          .map(arg => {\n            if (arg == null) {\n              return null;\n            } else if (typeof arg === 'string') {\n              return arg;\n            } else if (typeof arg === 'number' || typeof arg === 'boolean') {\n              return arg.toString();\n            } else if (arg instanceof Error) {\n              return arg.message;\n            } else {\n              try {\n                return JSON.stringify(arg);\n              } catch (ignored) {\n                return null;\n              }\n            }\n          })\n          .filter(arg => arg)\n          .join(' ');\n        if (level >= (customLogLevel ?? instance.logLevel)) {\n          logCallback({\n            level: LogLevel[level].toLowerCase() as LogLevelString,\n            message,\n            args,\n            type: instance.name\n          });\n        }\n      };\n    }\n  }\n}\n","/**\n * @license\n * Copyright 2024 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/** The semver (www.semver.org) version of the SDK. */\nexport let SDK_VERSION = '';\n\n/**\n * SDK_VERSION should be set before any database instance is created\n * @internal\n */\nexport function setSDKVersion(version: string): void {\n  SDK_VERSION = version;\n}\n","/**\n * @license\n * Copyright 2024 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { FirebaseError } from '@firebase/util';\n\nexport type DataConnectErrorCode =\n  | 'other'\n  | 'already-initialized'\n  | 'not-initialized'\n  | 'not-supported'\n  | 'invalid-argument'\n  | 'partial-error'\n  | 'unauthorized';\n\nexport type Code = DataConnectErrorCode;\n\nexport const Code = {\n  OTHER: 'other' as DataConnectErrorCode,\n  ALREADY_INITIALIZED: 'already-initialized' as DataConnectErrorCode,\n  NOT_INITIALIZED: 'not-initialized' as DataConnectErrorCode,\n  NOT_SUPPORTED: 'not-supported' as DataConnectErrorCode,\n  INVALID_ARGUMENT: 'invalid-argument' as DataConnectErrorCode,\n  PARTIAL_ERROR: 'partial-error' as DataConnectErrorCode,\n  UNAUTHORIZED: 'unauthorized' as DataConnectErrorCode\n};\n\n/** An error returned by a DataConnect operation. */\nexport class DataConnectError extends FirebaseError {\n  /** @internal */\n  readonly name: string = 'DataConnectError';\n\n  constructor(code: Code, message: string) {\n    super(code, message);\n\n    // Ensure the instanceof operator works as expected on subclasses of Error.\n    // See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error#custom_error_types\n    // and https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-2.html#support-for-newtarget\n    Object.setPrototypeOf(this, DataConnectError.prototype);\n  }\n\n  /** @internal */\n  toString(): string {\n    return `${this.name}[code=${this.code}]: ${this.message}`;\n  }\n}\n\n/** An error returned by a DataConnect operation. */\nexport class DataConnectOperationError extends DataConnectError {\n  /** @internal */\n  readonly name: string = 'DataConnectOperationError';\n\n  /** The response received from the backend. */\n  readonly response: DataConnectOperationFailureResponse;\n\n  /** @hideconstructor */\n  constructor(message: string, response: DataConnectOperationFailureResponse) {\n    super(Code.PARTIAL_ERROR, message);\n    this.response = response;\n  }\n}\n\nexport interface DataConnectOperationFailureResponse {\n  // The \"data\" provided by the backend in the response message.\n  //\n  // Will be `undefined` if no \"data\" was provided in the response message.\n  // Otherwise, will be `null` if `null` was explicitly specified as the \"data\"\n  // in the response message. Otherwise, will be the value of the \"data\"\n  // specified as the \"data\" in the response message\n  readonly data?: Record<string, unknown> | null;\n\n  // The list of errors provided by the backend in the response message.\n  readonly errors: DataConnectOperationFailureResponseErrorInfo[];\n}\n\n// Information about the error, as provided in the response from the backend.\n// See https://spec.graphql.org/draft/#sec-Errors\nexport interface DataConnectOperationFailureResponseErrorInfo {\n  // The error message.\n  readonly message: string;\n\n  // The path of the field in the response data to which this error relates.\n  // String values in this array refer to field names. Numeric values in this\n  // array always satisfy `Number.isInteger()` and refer to the index in an\n  // array.\n  readonly path: Array<string | number>;\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport type FDCScalarValue =\n  | string\n  | number\n  | boolean\n  | undefined\n  | null\n  | Record<string, unknown>\n  | FDCScalarValue[];\n\nexport interface EntityDataObjectJson {\n  map: {\n    [key: string]: FDCScalarValue;\n  };\n  referencedFrom: string[];\n  globalID: string;\n}\n\nexport class EntityDataObject {\n  getServerValue(key: string): unknown {\n    return this.serverValues[key];\n  }\n  private serverValues: { [key: string]: FDCScalarValue } = {};\n  private referencedFrom = new Set<string>();\n  constructor(public readonly globalID: string) {}\n  getServerValues(): { [key: string]: FDCScalarValue } {\n    return this.serverValues;\n  }\n  toJSON(): EntityDataObjectJson {\n    return {\n      globalID: this.globalID,\n      map: this.serverValues,\n      referencedFrom: Array.from(this.referencedFrom)\n    };\n  }\n  static fromJSON(json: EntityDataObjectJson): EntityDataObject {\n    const edo = new EntityDataObject(json.globalID);\n    edo.serverValues = json.map;\n    edo.referencedFrom = new Set(json.referencedFrom);\n    return edo;\n  }\n\n  updateServerValue(\n    key: string,\n    value: FDCScalarValue,\n    requestedFrom: string\n  ): string[] {\n    this.serverValues[key] = value;\n    this.referencedFrom.add(requestedFrom);\n    return Array.from(this.referencedFrom);\n  }\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { InternalCacheProvider } from './CacheProvider';\nimport { EntityDataObject } from './EntityDataObject';\nimport { ResultTree } from './ResultTree';\n\nexport class InMemoryCacheProvider implements InternalCacheProvider {\n  private edos = new Map<string, EntityDataObject>();\n  private resultTrees = new Map<string, ResultTree>();\n  constructor(private _keyId: string) {}\n\n  async setResultTree(queryId: string, rt: ResultTree): Promise<void> {\n    this.resultTrees.set(queryId, rt);\n  }\n  async getResultTree(queryId: string): Promise<ResultTree | undefined> {\n    return this.resultTrees.get(queryId);\n  }\n  async updateEntityData(entityData: EntityDataObject): Promise<void> {\n    this.edos.set(entityData.globalID, entityData);\n  }\n  async getEntityData(globalId: string): Promise<EntityDataObject> {\n    if (!this.edos.has(globalId)) {\n      this.edos.set(globalId, new EntityDataObject(globalId));\n    }\n    // Because of the above, we can guarantee that there will be an EDO at the globalId.\n    return this.edos.get(globalId)!;\n  }\n  close(): Promise<void> {\n    // No-op\n    return Promise.resolve();\n  }\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Code, DataConnectError } from '../core/error';\n\nimport { InternalCacheProvider } from './CacheProvider';\nimport {\n  EntityDataObject,\n  EntityDataObjectJson,\n  FDCScalarValue\n} from './EntityDataObject';\nimport { ImpactedQueryRefsAccumulator } from './ImpactedQueryRefsAccumulator';\n\nexport const GLOBAL_ID_KEY = '_id';\nexport const OBJECT_LISTS_KEY = '_objectLists';\nexport const REFERENCES_KEY = '_references';\nexport const SCALARS_KEY = '_scalars';\nexport const ENTITY_DATA_KEYS_KEY = '_entity_data_keys';\nexport class EntityNode {\n  entityData?: EntityDataObject;\n  scalars: Record<string, FDCScalarValue> = {};\n  references: { [key: string]: EntityNode } = {};\n  objectLists: {\n    [key: string]: EntityNode[];\n  } = {};\n  globalId?: string;\n  entityDataKeys: Set<string> = new Set();\n\n  async loadData(\n    queryId: string,\n    values: FDCScalarValue,\n    entityIds: Record<string, unknown> | undefined,\n    acc: ImpactedQueryRefsAccumulator,\n    cacheProvider: InternalCacheProvider\n  ): Promise<void> {\n    if (values === undefined) {\n      return;\n    }\n    if (typeof values !== 'object' || Array.isArray(values)) {\n      throw new DataConnectError(\n        Code.INVALID_ARGUMENT,\n        'EntityNode initialized with non-object value'\n      );\n    }\n    if (values === null) {\n      return;\n    }\n\n    if (\n      typeof values === 'object' &&\n      entityIds &&\n      entityIds[GLOBAL_ID_KEY] &&\n      typeof entityIds[GLOBAL_ID_KEY] === 'string'\n    ) {\n      this.globalId = entityIds[GLOBAL_ID_KEY];\n      this.entityData = await cacheProvider.getEntityData(this.globalId);\n    }\n    for (const key in values) {\n      if (values.hasOwnProperty(key)) {\n        if (typeof values[key] === 'object') {\n          if (Array.isArray(values[key])) {\n            const ids: Record<string, unknown> | undefined =\n              entityIds && (entityIds[key] as Record<string, unknown>);\n            const objArray: EntityNode[] = [];\n            const scalarArray: Array<NonNullable<FDCScalarValue>> = [];\n            for (const [index, value] of values[key].entries()) {\n              if (typeof value === 'object') {\n                if (Array.isArray(value)) {\n                  // Note: we don't support sparse arrays.\n                } else {\n                  const entityNode = new EntityNode();\n                  await entityNode.loadData(\n                    queryId,\n                    value,\n                    ids && (ids[index] as Record<string, unknown>),\n                    acc,\n                    cacheProvider\n                  );\n                  objArray.push(entityNode);\n                }\n              } else {\n                scalarArray.push(value);\n              }\n            }\n            if (scalarArray.length > 0 && objArray.length > 0) {\n              this.scalars[key] = values[key];\n            } else if (scalarArray.length > 0) {\n              if (this.entityData) {\n                const impactedRefs = this.entityData.updateServerValue(\n                  key,\n                  scalarArray,\n                  queryId\n                );\n                this.entityDataKeys.add(key);\n                acc.add(impactedRefs);\n              } else {\n                this.scalars[key] = scalarArray;\n              }\n            } else if (objArray.length > 0) {\n              this.objectLists[key] = objArray;\n            } else {\n              this.scalars[key] = [];\n            }\n          } else {\n            if (values[key] === null) {\n              this.scalars[key] = null;\n              continue;\n            }\n            const entityNode = new EntityNode();\n            // TODO: Load Data might need to be pushed into ResultTreeProcessor instead.\n            await entityNode.loadData(\n              queryId,\n              (values as Record<string, FDCScalarValue>)[key],\n              entityIds && (entityIds[key] as Record<string, unknown>),\n              acc,\n              cacheProvider\n            );\n            this.references[key] = entityNode;\n          }\n        } else {\n          if (this.entityData) {\n            const impactedRefs = this.entityData.updateServerValue(\n              key,\n              values[key] as FDCScalarValue,\n              queryId\n            );\n            this.entityDataKeys.add(key);\n            acc.add(impactedRefs);\n          } else {\n            this.scalars[key] = values[key] as FDCScalarValue;\n          }\n        }\n      }\n    }\n    if (this.entityData) {\n      await cacheProvider.updateEntityData(this.entityData);\n    }\n  }\n\n  toJSON(mode: EncodingMode): Record<string, unknown> {\n    const resultObject: Record<string, unknown> = {};\n    if (mode === EncodingMode.hydrated) {\n      if (this.entityData) {\n        for (const key of this.entityDataKeys) {\n          resultObject[key] = this.entityData.getServerValue(key);\n        }\n      }\n\n      if (this.scalars) {\n        Object.assign(resultObject, this.scalars);\n      }\n      if (this.references) {\n        for (const key in this.references) {\n          if (this.references.hasOwnProperty(key)) {\n            resultObject[key] = this.references[key].toJSON(mode);\n          }\n        }\n      }\n      if (this.objectLists) {\n        for (const key in this.objectLists) {\n          if (this.objectLists.hasOwnProperty(key)) {\n            resultObject[key] = this.objectLists[key].map(obj =>\n              obj.toJSON(mode)\n            );\n          }\n        }\n      }\n      return resultObject;\n    } else {\n      // Get JSON representation of dehydrated list\n      if (this.entityData) {\n        resultObject[GLOBAL_ID_KEY] = this.entityData.globalID;\n      }\n\n      resultObject[ENTITY_DATA_KEYS_KEY] = Array.from(this.entityDataKeys);\n\n      if (this.scalars) {\n        resultObject[SCALARS_KEY] = this.scalars;\n      }\n\n      if (this.references) {\n        const references = {} as Record<string, unknown>;\n        for (const key in this.references) {\n          if (this.references.hasOwnProperty(key)) {\n            references[key] = this.references[key].toJSON(mode);\n          }\n        }\n        resultObject[REFERENCES_KEY] = references;\n      }\n      if (this.objectLists) {\n        const objectLists = {} as Record<string, unknown>;\n        for (const key in this.objectLists) {\n          if (this.objectLists.hasOwnProperty(key)) {\n            objectLists[key] = this.objectLists[key].map(obj =>\n              obj.toJSON(mode)\n            );\n          }\n        }\n        resultObject[OBJECT_LISTS_KEY] = objectLists;\n      }\n    }\n\n    return resultObject;\n  }\n\n  static fromJson(obj: DehydratedStubDataObject): EntityNode {\n    const sdo = new EntityNode();\n    if (obj.backingData) {\n      sdo.entityData = EntityDataObject.fromJSON(obj.backingData);\n    }\n    sdo.globalId = obj.globalID;\n    sdo.scalars = obj.scalars;\n    if (obj.references) {\n      const references: Record<string, unknown> = {};\n      for (const key in obj.references) {\n        if (obj.references.hasOwnProperty(key)) {\n          references[key] = EntityNode.fromJson(obj.references[key]);\n        }\n      }\n      sdo.references = references as typeof sdo.references;\n    }\n    if (obj.objectLists) {\n      const objectLists: Record<string, unknown> = {};\n      for (const key in obj.objectLists) {\n        if (obj.objectLists.hasOwnProperty(key)) {\n          objectLists[key] = obj.objectLists[key].map(obj =>\n            EntityNode.fromJson(obj)\n          );\n        }\n      }\n      sdo.objectLists = objectLists as typeof sdo.objectLists;\n    }\n    return sdo;\n  }\n}\n\nexport interface DehydratedStubDataObject {\n  backingData?: EntityDataObjectJson;\n  globalID?: string;\n  scalars: { [key: string]: FDCScalarValue };\n  references: { [key: string]: DehydratedStubDataObject };\n  objectLists: {\n    [key: string]: DehydratedStubDataObject[];\n  };\n}\n\n// Helpful for storing in persistent cache, which is not available yet.\nexport enum EncodingMode {\n  hydrated,\n  dehydrated\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { EntityNode, DehydratedStubDataObject } from './EntityNode';\n\nexport class ResultTree {\n  /**\n   * Create a {@link ResultTree} from a dehydrated JSON object.\n   * @param value The dehydrated JSON object.\n   * @returns The {@link ResultTree}.\n   */\n  static fromJson(value: DehydratedResultTreeJson): ResultTree {\n    return new ResultTree(\n      EntityNode.fromJson(value.rootStub),\n      value.maxAge,\n      value.cachedAt,\n      value.lastAccessed\n    );\n  }\n  constructor(\n    private rootStub: EntityNode,\n    private maxAge: number = 0,\n    public readonly cachedAt: Date,\n    private _lastAccessed: Date\n  ) {}\n  isStale(): boolean {\n    return (\n      Date.now() - new Date(this.cachedAt.getTime()).getTime() >\n      this.maxAge * 1000\n    );\n  }\n  updateMaxAge(maxAgeInSeconds: number): void {\n    this.maxAge = maxAgeInSeconds;\n  }\n  updateAccessed(): void {\n    this._lastAccessed = new Date();\n  }\n  get lastAccessed(): Date {\n    return this._lastAccessed;\n  }\n  getRootStub(): EntityNode {\n    return this.rootStub;\n  }\n}\n\ninterface DehydratedResultTreeJson {\n  rootStub: DehydratedStubDataObject;\n  maxAge: number;\n  cachedAt: Date;\n  lastAccessed: Date;\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport class ImpactedQueryRefsAccumulator {\n  impacted = new Set<string>();\n  constructor(private queryId: string) {}\n  add(impacted: string[]): void {\n    impacted\n      .filter(ref => ref !== this.queryId)\n      .forEach(ref => this.impacted.add(ref));\n  }\n  consumeEvents(): string[] {\n    const events = Array.from(this.impacted);\n    this.impacted.clear();\n    return events;\n  }\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { InternalCacheProvider } from './CacheProvider';\nimport { EncodingMode, EntityNode } from './EntityNode';\nimport { ImpactedQueryRefsAccumulator } from './ImpactedQueryRefsAccumulator';\n\ninterface DehydratedResults {\n  entityNode: EntityNode;\n  impacted: string[];\n}\n\nexport class ResultTreeProcessor {\n  /**\n   * Hydrate the EntityNode into a JSON object so that it can be returned to the user.\n   * @param rootStubObject\n   * @returns {string}\n   */\n  hydrateResults(rootStubObject: EntityNode): Record<string, unknown> {\n    return rootStubObject.toJSON(EncodingMode.hydrated);\n  }\n  /**\n   * Dehydrate results so that they can be stored in the cache.\n   * @param json\n   * @param entityIds\n   * @param cacheProvider\n   * @param queryId\n   * @returns {Promise<DehydratedResults>}\n   */\n  async dehydrateResults(\n    json: Record<string, unknown>,\n    entityIds: Record<string, unknown>,\n    cacheProvider: InternalCacheProvider,\n    queryId: string\n  ): Promise<DehydratedResults> {\n    const acc = new ImpactedQueryRefsAccumulator(queryId);\n    const entityNode = new EntityNode();\n    await entityNode.loadData(queryId, json, entityIds, acc, cacheProvider);\n    return {\n      entityNode,\n      impacted: acc.consumeEvents()\n    };\n  }\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { generateSHA256Hash } from '@firebase/util';\n\nimport {\n  CacheProvider,\n  CacheSettings,\n  type ConnectorConfig\n} from '../api/DataConnect';\nimport { Code, DataConnectError } from '../core/error';\nimport { type AuthTokenProvider } from '../core/FirebaseAuthProvider';\n\nimport { InternalCacheProvider } from './CacheProvider';\nimport { InMemoryCacheProvider } from './InMemoryCacheProvider';\nimport { ResultTree } from './ResultTree';\nimport { ResultTreeProcessor } from './ResultTreeProcessor';\n\nexport const Memory = 'memory';\n\nexport type DataConnectStorage = typeof Memory;\n\n/**\n * ServerValues\n */\nexport interface ServerValues extends Record<string, unknown> {\n  maxAge?: number;\n}\n\nexport class DataConnectCache {\n  private cacheProvider: InternalCacheProvider | null = null;\n  private uid: string | null = null;\n  constructor(\n    private authProvider: AuthTokenProvider,\n    private projectId: string,\n    private connectorConfig: ConnectorConfig,\n    private host: string,\n    public cacheSettings: CacheSettings\n  ) {\n    this.authProvider.addTokenChangeListener(async _ => {\n      const newUid = this.authProvider.getAuth().getUid();\n      // We should only close if the token changes and so does the new UID\n      if (this.uid !== newUid) {\n        this.cacheProvider?.close();\n        this.uid = newUid;\n        const identifier = await this.getIdentifier(this.uid);\n        this.cacheProvider = this.initializeNewProviders(identifier);\n      }\n    });\n  }\n\n  async initialize(): Promise<void> {\n    if (!this.cacheProvider) {\n      const identifier = await this.getIdentifier(this.uid);\n      this.cacheProvider = this.initializeNewProviders(identifier);\n    }\n  }\n\n  async getIdentifier(uid: string | null): Promise<string> {\n    const identifier = `${\n      'memory' // TODO: replace this with indexeddb when persistence is available.\n    }-${this.projectId}-${this.connectorConfig.service}-${\n      this.connectorConfig.connector\n    }-${this.connectorConfig.location}-${uid}-${this.host}`;\n    const sha256 = await generateSHA256Hash(identifier);\n    return sha256;\n  }\n\n  initializeNewProviders(identifier: string): InternalCacheProvider {\n    return this.cacheSettings.cacheProvider.initialize(identifier);\n  }\n\n  async containsResultTree(queryId: string): Promise<boolean> {\n    await this.initialize();\n    const resultTree = await this.cacheProvider!.getResultTree(queryId);\n    return resultTree !== undefined;\n  }\n  async getResultTree(queryId: string): Promise<ResultTree | undefined> {\n    await this.initialize();\n    return this.cacheProvider!.getResultTree(queryId);\n  }\n  async getResultJSON(queryId: string): Promise<Record<string, unknown>> {\n    await this.initialize();\n    const processor = new ResultTreeProcessor();\n    const cacheProvider = this.cacheProvider;\n    const resultTree = await cacheProvider!.getResultTree(queryId);\n    if (!resultTree) {\n      throw new DataConnectError(\n        Code.INVALID_ARGUMENT,\n        `${queryId} not found in cache. Call \"update()\" first.`\n      );\n    }\n    return processor.hydrateResults(resultTree.getRootStub());\n  }\n  async update(\n    queryId: string,\n    serverValues: ServerValues,\n    entityIds: Record<string, unknown>\n  ): Promise<string[]> {\n    await this.initialize();\n    const processor = new ResultTreeProcessor();\n    const cacheProvider = this.cacheProvider;\n    const { entityNode: stubDataObject, impacted } =\n      await processor.dehydrateResults(\n        serverValues,\n        entityIds,\n        cacheProvider!,\n        queryId\n      );\n    const now = new Date();\n    await cacheProvider!.setResultTree(\n      queryId,\n      new ResultTree(\n        stubDataObject,\n        serverValues.maxAge || this.cacheSettings.maxAgeSeconds,\n        now,\n        now\n      )\n    );\n    return impacted;\n  }\n}\n\nexport class MemoryStub implements CacheProvider<'MEMORY'> {\n  type: 'MEMORY' = 'MEMORY';\n  /**\n   * @internal\n   */\n  initialize(cacheId: string): InMemoryCacheProvider {\n    return new InMemoryCacheProvider(cacheId);\n  }\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @public\n * Generates a SHA-256 hash for the given input string.\n *\n * @param input The string to hash.\n * @returns A promise that resolves to the SHA-256 hash as a hex string.\n */\nexport async function generateSHA256Hash(input: string): Promise<string> {\n  const textEncoder = new TextEncoder();\n  const data = textEncoder.encode(input);\n  const hashBuffer = await crypto.subtle.digest('SHA-256', data);\n\n  // Convert ArrayBuffer to hex string\n  const hashArray = Array.from(new Uint8Array(hashBuffer));\n  const hexHash = hashArray.map(b => b.toString(16).padStart(2, '0')).join('');\n  return hexHash;\n}\n","/**\n * @license\n * Copyright 2024 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { FirebaseApp, _isFirebaseServerApp } from '@firebase/app';\nimport {\n  AppCheckInternalComponentName,\n  AppCheckTokenListener,\n  AppCheckTokenResult,\n  FirebaseAppCheckInternal\n} from '@firebase/app-check-interop-types';\nimport { Provider } from '@firebase/component';\n\n/**\n * @internal\n * Abstraction around AppCheck's token fetching capabilities.\n */\nexport class AppCheckTokenProvider {\n  private appCheck?: FirebaseAppCheckInternal | null;\n  private serverAppAppCheckToken?: string;\n  constructor(\n    app: FirebaseApp,\n    private appCheckProvider?: Provider<AppCheckInternalComponentName>\n  ) {\n    if (_isFirebaseServerApp(app) && app.settings.appCheckToken) {\n      this.serverAppAppCheckToken = app.settings.appCheckToken;\n    }\n    this.appCheck = appCheckProvider?.getImmediate({ optional: true });\n    if (!this.appCheck) {\n      void appCheckProvider\n        ?.get()\n        .then(appCheck => (this.appCheck = appCheck))\n        .catch();\n    }\n  }\n\n  getToken(): Promise<AppCheckTokenResult | null> {\n    if (this.serverAppAppCheckToken) {\n      return Promise.resolve({ token: this.serverAppAppCheckToken });\n    }\n\n    if (!this.appCheck) {\n      return new Promise<AppCheckTokenResult | null>((resolve, reject) => {\n        // Support delayed initialization of FirebaseAppCheck. This allows our\n        // customers to initialize the RTDB SDK before initializing Firebase\n        // AppCheck and ensures that all requests are authenticated if a token\n        // becomes available before the timoeout below expires.\n        setTimeout(() => {\n          if (this.appCheck) {\n            this.getToken().then(resolve, reject);\n          } else {\n            resolve(null);\n          }\n        }, 0);\n      });\n    }\n    return this.appCheck.getToken();\n  }\n\n  addTokenChangeListener(listener: AppCheckTokenListener): void {\n    void this.appCheckProvider\n      ?.get()\n      .then(appCheck => appCheck.addTokenListener(listener));\n  }\n}\n","/**\n * @license\n * Copyright 2024 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { Logger, LogLevelString } from '@firebase/logger';\n\nimport { SDK_VERSION } from './core/version';\n\nconst logger = new Logger('@firebase/data-connect');\nexport function setLogLevel(logLevel: LogLevelString): void {\n  logger.setLogLevel(logLevel);\n}\nexport function logDebug(msg: string): void {\n  logger.debug(`DataConnect (${SDK_VERSION}): ${msg}`);\n}\n\nexport function logError(msg: string): void {\n  logger.error(`DataConnect (${SDK_VERSION}): ${msg}`);\n}\n","/**\n * @license\n * Copyright 2024 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { FirebaseOptions } from '@firebase/app-types';\nimport {\n  FirebaseAuthInternal,\n  FirebaseAuthInternalName,\n  FirebaseAuthTokenData\n} from '@firebase/auth-interop-types';\nimport { Provider } from '@firebase/component';\n\nimport { logDebug, logError } from '../logger';\n\n// @internal\nexport interface AuthTokenProvider {\n  getToken(forceRefresh: boolean): Promise<FirebaseAuthTokenData | null>;\n  addTokenChangeListener(listener: AuthTokenListener): void;\n  getAuth(): FirebaseAuthInternal;\n}\nexport type AuthTokenListener = (token: string | null) => void;\n\n// @internal\nexport class FirebaseAuthProvider implements AuthTokenProvider {\n  private _auth: FirebaseAuthInternal;\n  constructor(\n    private _appName: string,\n    private _options: FirebaseOptions,\n    private _authProvider: Provider<FirebaseAuthInternalName>\n  ) {\n    this._auth = _authProvider.getImmediate({ optional: true })!;\n    if (!this._auth) {\n      _authProvider.onInit(auth => (this._auth = auth));\n    }\n  }\n  getAuth(): FirebaseAuthInternal {\n    return this._auth;\n  }\n  getToken(forceRefresh: boolean): Promise<FirebaseAuthTokenData | null> {\n    if (!this._auth) {\n      return new Promise((resolve, reject) => {\n        setTimeout(() => {\n          if (this._auth) {\n            this.getToken(forceRefresh).then(resolve, reject);\n          } else {\n            resolve(null);\n          }\n        }, 0);\n      });\n    }\n    return this._auth.getToken(forceRefresh).catch(error => {\n      if (error && error.code === 'auth/token-not-initialized') {\n        logDebug(\n          'Got auth/token-not-initialized error.  Treating as null token.'\n        );\n        return null;\n      } else {\n        logError(\n          'Error received when attempting to retrieve token: ' +\n            JSON.stringify(error)\n        );\n        return Promise.reject(error);\n      }\n    });\n  }\n  addTokenChangeListener(listener: AuthTokenListener): void {\n    this._auth?.addAuthTokenListener(listener);\n  }\n  removeTokenChangeListener(listener: (token: string | null) => void): void {\n    this._authProvider\n      .get()\n      .then(auth => auth.removeAuthTokenListener(listener))\n      .catch(err => logError(err));\n  }\n}\n","/**\n * @license\n * Copyright 2024 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Extensions } from '../network';\n\nimport { DataConnect, DataConnectOptions } from './DataConnect';\nexport const QUERY_STR = 'query';\nexport const MUTATION_STR = 'mutation';\nexport type ReferenceType = typeof QUERY_STR | typeof MUTATION_STR;\n\nexport const SOURCE_SERVER = 'SERVER';\nexport const SOURCE_CACHE = 'CACHE';\nexport type DataSource = typeof SOURCE_CACHE | typeof SOURCE_SERVER;\n\nexport interface OpResult<Data> {\n  data: Data;\n  source: DataSource;\n  fetchTime: string;\n  extensions?: Extensions;\n}\n\nexport interface OperationRef<_Data, Variables> {\n  name: string;\n  variables: Variables;\n  refType: ReferenceType;\n  dataConnect: DataConnect;\n}\n\nexport interface DataConnectResult<Data, Variables> extends OpResult<Data> {\n  ref: OperationRef<Data, Variables>;\n  // future metadata\n}\n\n/**\n * Serialized RefInfo as a result of `QueryResult.toJSON().refInfo`\n */\nexport interface RefInfo<Variables> {\n  name: string;\n  variables: Variables;\n  connectorConfig: DataConnectOptions;\n}\n/**\n * Serialized Ref as a result of `QueryResult.toJSON()`\n */\nexport interface SerializedRef<Data, Variables> extends OpResult<Data> {\n  refInfo: RefInfo<Variables>;\n}\n","/**\n * @license\n * Copyright 2026 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { OpResult } from '../api/Reference';\nimport { DataConnectExtension } from '../network';\nexport function parseEntityIds<T>(\n  result: OpResult<T>\n): Record<string, unknown> {\n  // Iterate through extensions.dataConnect\n  const dataConnectExtensions = result.extensions?.dataConnect;\n  const dataCopy = Object.assign(result);\n  if (!dataConnectExtensions) {\n    return dataCopy;\n  }\n  const ret: Record<string, unknown> = {};\n  for (const extension of dataConnectExtensions) {\n    const { path } = extension;\n    populatePath(path, ret, extension);\n  }\n  return ret;\n}\n\n// mutates the object to update the path\nexport function populatePath(\n  path: Array<string | number>,\n  toUpdate: Record<string | number, unknown>,\n  extension: DataConnectExtension\n): void {\n  let curObj: Record<string | number, unknown> = toUpdate;\n  for (const slice of path) {\n    if (typeof curObj[slice] !== 'object') {\n      curObj[slice] = {};\n    }\n    curObj = curObj[slice] as Record<string, unknown>;\n  }\n\n  if ('entityId' in extension && extension.entityId) {\n    curObj['_id'] = extension.entityId;\n  } else if ('entityIds' in extension) {\n    const entityArr = extension.entityIds;\n    for (let i = 0; i < entityArr.length; i++) {\n      const entityId = entityArr[i];\n      if (typeof curObj[i] === 'undefined') {\n        curObj[i] = {};\n      }\n      (curObj[i] as Record<string, unknown>)._id = entityId;\n    }\n  }\n}\n","/**\n * @license\n * Copyright 2024 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport type HmacImpl = (obj: Record<string, unknown>) => string;\nexport let encoderImpl: HmacImpl;\nexport type DecodeHmacImpl = (s: string) => Record<string, unknown>;\nexport let decoderImpl: DecodeHmacImpl;\nexport function setEncoder(encoder: HmacImpl): void {\n  encoderImpl = encoder;\n}\nexport function setDecoder(decoder: DecodeHmacImpl): void {\n  decoderImpl = decoder;\n}\nfunction sortKeysForObj(o: Record<string, unknown>): Record<string, unknown> {\n  return Object.keys(o)\n    .sort()\n    .reduce((accumulator, currentKey) => {\n      accumulator[currentKey] = o[currentKey];\n      return accumulator;\n    }, {} as Record<string, unknown>);\n}\nsetEncoder((o: Record<string, unknown>) => JSON.stringify(sortKeysForObj(o)));\nsetDecoder(s => sortKeysForObj(JSON.parse(s)));\n","/**\n * @license\n * Copyright 2024 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { type DataConnect } from '../../api/DataConnect';\nimport { QueryRef, QueryResult } from '../../api/query';\nimport {\n  QUERY_STR,\n  SerializedRef,\n  SOURCE_SERVER,\n  DataSource,\n  SOURCE_CACHE\n} from '../../api/Reference';\nimport { DataConnectSubscription } from '../../api.browser';\nimport { DataConnectCache, ServerValues } from '../../cache/Cache';\nimport { parseEntityIds } from '../../cache/cacheUtils';\nimport { EncodingMode } from '../../cache/EntityNode';\nimport {\n  DataConnectTransportInterface,\n  Extensions,\n  DataConnectExtensionWithMaxAge,\n  ExtensionsWithMaxAge,\n  SubscribeObserver,\n  DataConnectResponse\n} from '../../network';\nimport { decoderImpl, encoderImpl } from '../../util/encoder';\nimport {\n  Code,\n  DataConnectError,\n  DataConnectOperationError,\n  DataConnectOperationFailureResponse\n} from '../error';\n\nimport {\n  OnCompleteSubscription,\n  OnErrorSubscription,\n  OnResultSubscription\n} from './subscribe';\n\nexport function getRefSerializer<Data, Variables>(\n  queryRef: QueryRef<Data, Variables>,\n  data: Data,\n  source: DataSource,\n  fetchTime: string\n) {\n  return function toJSON(): SerializedRef<Data, Variables> {\n    return {\n      data,\n      refInfo: {\n        name: queryRef.name,\n        variables: queryRef.variables,\n        connectorConfig: {\n          projectId: queryRef.dataConnect.app.options.projectId!,\n          ...queryRef.dataConnect.getSettings()\n        }\n      },\n      fetchTime,\n      source\n    };\n  };\n}\n\nexport class QueryManager {\n  async preferCacheResults<Data, Variables>(\n    queryRef: QueryRef<Data, Variables>,\n    allowStale = false\n  ): Promise<QueryResult<Data, Variables>> {\n    let cacheResult: QueryResult<Data, Variables> | undefined;\n    try {\n      cacheResult = await this.fetchCacheResults(queryRef, allowStale);\n    } catch (e) {\n      // Ignore the error and try to fetch from the server.\n    }\n    if (cacheResult) {\n      return cacheResult;\n    }\n    return this.fetchServerResults(queryRef);\n  }\n  private callbacks = new Map<\n    string,\n    Array<DataConnectSubscription<unknown, unknown>>\n  >();\n  /**\n   * Map of serialized query keys to most recent Query Result. Used as a simple fallback cache\n   * for subsciptions if caching is not enabled.\n   */\n  private subscriptionCache = new Map<string, QueryResult<unknown, unknown>>();\n  constructor(\n    private transport: DataConnectTransportInterface,\n    private dc: DataConnect,\n    private cache?: DataConnectCache\n  ) {}\n  private queue: Array<Promise<unknown>> = [];\n  async waitForQueuedWrites(): Promise<void> {\n    for (const promise of this.queue) {\n      await promise;\n    }\n    this.queue = [];\n  }\n\n  updateSSR<Data, Variables>(updatedData: QueryResult<Data, Variables>): void {\n    this.queue.push(\n      this.updateCache(updatedData).then(async result =>\n        this.publishCacheResultsToSubscribers(result, updatedData.fetchTime)\n      )\n    );\n  }\n\n  async updateCache<Data, Variables>(\n    result: QueryResult<Data, Variables>,\n    extensions?: DataConnectExtensionWithMaxAge[]\n  ): Promise<string[]> {\n    await this.waitForQueuedWrites();\n    if (this.cache) {\n      const entityIds = parseEntityIds(result);\n      const updatedMaxAge = getMaxAgeFromExtensions(extensions);\n      if (updatedMaxAge !== undefined) {\n        this.cache.cacheSettings.maxAgeSeconds = updatedMaxAge;\n      }\n      return this.cache.update(\n        encoderImpl({\n          name: result.ref.name,\n          variables: result.ref.variables,\n          refType: QUERY_STR\n        }),\n        result.data as ServerValues,\n        entityIds\n      );\n    } else {\n      const key = encoderImpl({\n        name: result.ref.name,\n        variables: result.ref.variables,\n        refType: QUERY_STR\n      });\n      this.subscriptionCache.set(key, result);\n      return [key];\n    }\n  }\n\n  addSubscription<Data, Variables>(\n    queryRef: QueryRef<Data, Variables>,\n    onResultCallback: OnResultSubscription<Data, Variables>,\n    onCompleteCallback?: OnCompleteSubscription,\n    onErrorCallback?: OnErrorSubscription,\n    initialCache?: QueryResult<Data, Variables>\n  ): () => void {\n    const key = encoderImpl({\n      name: queryRef.name,\n      variables: queryRef.variables,\n      refType: QUERY_STR\n    });\n\n    const unsubscribe = (): void => {\n      if (this.callbacks.has(key)) {\n        const callbackList = this.callbacks.get(key)!;\n        const newList = callbackList.filter(\n          callback => callback !== subscription\n        );\n        this.callbacks.set(key, newList);\n\n        if (newList.length === 0) {\n          this.callbacks.delete(key);\n          this.transport.invokeUnsubscribe(queryRef.name, queryRef.variables);\n        }\n        onCompleteCallback?.();\n      }\n    };\n    const subscription: DataConnectSubscription<Data, Variables> = {\n      userCallback: onResultCallback,\n      errCallback: onErrorCallback,\n      unsubscribe\n    };\n\n    if (initialCache) {\n      this.updateSSR(initialCache);\n    }\n\n    const promise = this.preferCacheResults(queryRef, /*allowStale=*/ true);\n    // We want to ignore the error and let subscriptions handle it\n    promise.then(undefined, err => {});\n\n    if (this.callbacks.has(key)) {\n      this.callbacks\n        .get(key)!\n        .push(subscription as DataConnectSubscription<unknown, unknown>);\n    } else {\n      this.callbacks.set(key, [\n        subscription as DataConnectSubscription<unknown, unknown>\n      ]);\n\n      // only invoke subscription if we don't already have an active subscription\n      this.transport.invokeSubscribe<Data, Variables>(\n        this.makeSubscribeObserver(queryRef),\n        queryRef.name,\n        queryRef.variables\n      );\n    }\n\n    return unsubscribe;\n  }\n\n  async fetchServerResults<Data, Variables>(\n    queryRef: QueryRef<Data, Variables>\n  ): Promise<QueryResult<Data, Variables>> {\n    await this.waitForQueuedWrites();\n    const key = encoderImpl({\n      name: queryRef.name,\n      variables: queryRef.variables,\n      refType: QUERY_STR\n    });\n    try {\n      const result = await this.transport.invokeQuery<Data, Variables>(\n        queryRef.name,\n        queryRef.variables\n      );\n      const fetchTime = Date.now().toString();\n      const originalExtensions = result.extensions;\n      const queryResult: QueryResult<Data, Variables> = {\n        ...result,\n        ref: queryRef,\n        source: SOURCE_SERVER,\n        fetchTime,\n        data: result.data,\n        extensions: getDataConnectExtensionsWithoutMaxAge(originalExtensions),\n        toJSON: getRefSerializer(\n          queryRef,\n          result.data,\n          SOURCE_SERVER,\n          fetchTime\n        )\n      };\n      const updatedKeys = await this.updateCache(\n        queryResult,\n        originalExtensions?.dataConnect\n      );\n      this.publishDataToSubscribers(key, queryResult);\n      if (this.cache) {\n        await this.publishCacheResultsToSubscribers(updatedKeys, fetchTime);\n      } else {\n        this.subscriptionCache.set(key, queryResult);\n      }\n      return queryResult;\n    } catch (e) {\n      this.publishErrorToSubscribers(key, e);\n      throw e;\n    }\n  }\n\n  async fetchCacheResults<Data, Variables>(\n    queryRef: QueryRef<Data, Variables>,\n    allowStale = false\n  ): Promise<QueryResult<Data, Variables>> {\n    await this.waitForQueuedWrites();\n    let result: QueryResult<Data, Variables> | undefined | null;\n    if (!this.cache) {\n      result = await this.getFromSubscriberCache(queryRef);\n    } else {\n      result = await this.getFromResultTreeCache(queryRef, allowStale);\n    }\n    if (!result) {\n      throw new DataConnectError(\n        Code.OTHER,\n        'No cache entry found for query: ' + queryRef.name\n      );\n    }\n    const fetchTime = Date.now().toString();\n    const queryResult: QueryResult<Data, Variables> = {\n      ...result,\n      ref: queryRef,\n      source: SOURCE_CACHE,\n      fetchTime,\n      data: result.data,\n      extensions: result.extensions,\n      toJSON: getRefSerializer(queryRef, result.data, SOURCE_CACHE, fetchTime)\n    };\n    if (this.cache) {\n      const key = encoderImpl({\n        name: queryRef.name,\n        variables: queryRef.variables,\n        refType: QUERY_STR\n      });\n      await this.publishCacheResultsToSubscribers([key], fetchTime);\n    } else {\n      const key = encoderImpl({\n        name: queryRef.name,\n        variables: queryRef.variables,\n        refType: QUERY_STR\n      });\n      this.subscriptionCache.set(key, queryResult);\n      this.publishDataToSubscribers(key, queryResult);\n    }\n\n    return queryResult;\n  }\n\n  publishErrorToSubscribers(key: string, err: unknown): void {\n    this.callbacks.get(key)?.forEach(subscription => {\n      if (subscription.errCallback) {\n        subscription.errCallback(err as DataConnectError);\n      }\n    });\n  }\n\n  async getFromResultTreeCache<Data, Variables>(\n    queryRef: QueryRef<Data, Variables>,\n    allowStale = false\n  ): Promise<QueryResult<Data, Variables> | null> {\n    const key = encoderImpl({\n      name: queryRef.name,\n      variables: queryRef.variables,\n      refType: QUERY_STR\n    });\n    if (!this.cache || !(await this.cache.containsResultTree(key))) {\n      return null;\n    }\n    const cacheResult: Data = (await this.cache!.getResultJSON(key)) as Data;\n    const resultTree = await this.cache!.getResultTree(key);\n    if (!allowStale && resultTree!.isStale()) {\n      return null;\n    }\n    const result: QueryResult<Data, Variables> = {\n      source: SOURCE_CACHE,\n      ref: queryRef,\n      data: cacheResult,\n      toJSON: getRefSerializer(\n        queryRef,\n        cacheResult,\n        SOURCE_CACHE,\n        resultTree!.cachedAt.toString()\n      ),\n      fetchTime: resultTree!.cachedAt.toString()\n    };\n    (await this.cache!.getResultTree(key))!.updateAccessed();\n    return result;\n  }\n  async getFromSubscriberCache<Data, Variables>(\n    queryRef: QueryRef<Data, Variables>\n  ): Promise<QueryResult<Data, Variables> | undefined> {\n    const key = encoderImpl({\n      name: queryRef.name,\n      variables: queryRef.variables,\n      refType: QUERY_STR\n    });\n    if (!this.subscriptionCache.has(key)) {\n      return;\n    }\n    const result = this.subscriptionCache.get(key);\n    result!.source = SOURCE_CACHE;\n    result!.toJSON = getRefSerializer(\n      result!.ref,\n      result!.data,\n      SOURCE_CACHE,\n      result!.fetchTime\n    );\n    return result as QueryResult<Data, Variables>;\n  }\n\n  /** Call the registered onNext callbacks for the given key */\n  publishDataToSubscribers(\n    key: string,\n    queryResult: QueryResult<unknown, unknown>\n  ): void {\n    if (!this.callbacks.has(key)) {\n      return;\n    }\n    const subscribers = this.callbacks.get(key);\n    subscribers!.forEach(callback => {\n      callback.userCallback(queryResult);\n    });\n  }\n  async publishCacheResultsToSubscribers(\n    impactedQueries: string[],\n    fetchTime: string\n  ): Promise<void> {\n    if (!this.cache) {\n      return;\n    }\n    for (const query of impactedQueries) {\n      const callbacks = this.callbacks.get(query);\n      if (!callbacks) {\n        continue;\n      }\n      const newJson = (await this.cache.getResultTree(query))!\n        .getRootStub()\n        .toJSON(EncodingMode.hydrated);\n      const { name, variables } = decoderImpl(query) as unknown as QueryRef<\n        unknown,\n        unknown\n      >;\n      const queryRef: QueryRef<unknown, unknown> = {\n        dataConnect: this.dc,\n        refType: QUERY_STR,\n        name,\n        variables\n      };\n      this.publishDataToSubscribers(query, {\n        data: newJson,\n        fetchTime,\n        ref: queryRef,\n        source: SOURCE_CACHE,\n        toJSON: getRefSerializer(queryRef, newJson, SOURCE_CACHE, fetchTime)\n      });\n    }\n  }\n  enableEmulator(host: string, port: number): void {\n    this.transport.useEmulator(host, port);\n  }\n\n  /**\n   * Create a new {@link SubscribeObserver} for the given QueryRef. This will be passed to\n   * {@link DataConnectTransportInterface.invokeSubscribe | invokeSubscribe()} to notify the query\n   * layer of data update notifications or if the stream disconnected.\n   */\n  private makeSubscribeObserver<Data, Variables>(\n    queryRef: QueryRef<Data, Variables>\n  ): SubscribeObserver<Data> {\n    const key = encoderImpl({\n      name: queryRef.name,\n      variables: queryRef.variables,\n      refType: QUERY_STR\n    });\n    return {\n      onData: async response => {\n        await this.handleStreamNotification(key, response, queryRef);\n      },\n      onDisconnect: (code, reason) => {\n        this.handleStreamDisconnect(key, code, reason);\n      },\n      onError: error => {\n        this.publishErrorToSubscribers(key, error);\n      }\n    };\n  }\n\n  /**\n   * Handle a data update notification from the stream. Notify subscribers of results/errors, and\n   * update the cache.\n   */\n  private async handleStreamNotification<Data, Variables>(\n    key: string,\n    response: DataConnectResponse<Data>,\n    queryRef: QueryRef<Data, Variables>\n  ): Promise<void> {\n    if (response.errors && response.errors.length > 0) {\n      const stringified = JSON.stringify(\n        response.errors.map(e => {\n          if (e && typeof e === 'object') {\n            return {\n              message: (e as unknown as { message: string }).message,\n              code: (e as unknown as { code?: unknown }).code\n            };\n          }\n          return e;\n        })\n      );\n      const failureResponse: DataConnectOperationFailureResponse = {\n        errors: response.errors as [],\n        data: response.data as Record<string, unknown>\n      };\n      const error = new DataConnectOperationError(\n        'DataConnect error received from subscribe notification: ' +\n          stringified,\n        failureResponse\n      );\n      this.publishErrorToSubscribers(key, error);\n      return;\n    }\n\n    const fetchTime = Date.now().toString();\n    const queryResult: QueryResult<Data, Variables> = {\n      ref: queryRef,\n      source: SOURCE_SERVER,\n      fetchTime,\n      data: response.data,\n      extensions: getDataConnectExtensionsWithoutMaxAge(response.extensions),\n      toJSON: getRefSerializer(\n        queryRef,\n        response.data,\n        SOURCE_SERVER,\n        fetchTime\n      )\n    };\n    const updatedKeys = await this.updateCache(\n      queryResult,\n      response.extensions?.dataConnect\n    );\n    this.publishDataToSubscribers(key, queryResult);\n    if (this.cache) {\n      await this.publishCacheResultsToSubscribers(updatedKeys, fetchTime);\n    }\n  }\n\n  /**\n   * Handle a disconnect from the stream. Unsubscribe all callbacks for the given key.\n   */\n  private handleStreamDisconnect(\n    key: string,\n    code: string,\n    reason: string\n  ): void {\n    const error = new DataConnectError(code as Code, reason);\n    this.publishErrorToSubscribers(key, error);\n\n    const callbacks = this.callbacks.get(key);\n    if (callbacks) {\n      [...callbacks].forEach(cb => cb.unsubscribe());\n    }\n    return;\n  }\n}\n\nexport function getMaxAgeFromExtensions(\n  extensions: DataConnectExtensionWithMaxAge[] | undefined\n): number | undefined {\n  if (!extensions) {\n    return;\n  }\n  for (const extension of extensions) {\n    if (\n      'maxAge' in extension &&\n      extension.maxAge !== undefined &&\n      extension.maxAge !== null\n    ) {\n      if (extension.maxAge.endsWith('s')) {\n        return Number(\n          extension.maxAge.substring(0, extension.maxAge.length - 1)\n        );\n      }\n    }\n  }\n}\nfunction getDataConnectExtensionsWithoutMaxAge(\n  extensions: ExtensionsWithMaxAge\n): Extensions | undefined {\n  return {\n    dataConnect: extensions.dataConnect?.filter(\n      extension => 'entityId' in extension || 'entityIds' in extension\n    )\n  };\n}\n","/**\n * @license\n * Copyright 2024 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { DataConnectOptions, TransportOptions } from '../api/DataConnect';\nimport { AppCheckTokenProvider } from '../core/AppCheckTokenProvider';\nimport { Code, DataConnectError } from '../core/error';\nimport { AuthTokenProvider } from '../core/FirebaseAuthProvider';\nimport { SDK_VERSION } from '../core/version';\nimport { logDebug } from '../logger';\n\n/**\n * enum representing different flavors of the SDK used by developers\n * use the CallerSdkType for type-checking, and the CallerSdkTypeEnum for value-checking/assigning\n */\nexport type CallerSdkType =\n  | 'Base' // Core JS SDK\n  | 'Generated' // Generated JS SDK\n  | 'TanstackReactCore' // Tanstack non-generated React SDK\n  | 'GeneratedReact' // Generated React SDK\n  | 'TanstackAngularCore' // Tanstack non-generated Angular SDK\n  | 'GeneratedAngular'; // Generated Angular SDK\nexport const CallerSdkTypeEnum = {\n  Base: 'Base', // Core JS SDK\n  Generated: 'Generated', // Generated JS SDK\n  TanstackReactCore: 'TanstackReactCore', // Tanstack non-generated React SDK\n  GeneratedReact: 'GeneratedReact', // Tanstack non-generated Angular SDK\n  TanstackAngularCore: 'TanstackAngularCore', // Tanstack non-generated Angular SDK\n  GeneratedAngular: 'GeneratedAngular' // Generated Angular SDK\n} as const;\n\nexport interface DataConnectEntityArray {\n  entityIds: string[];\n}\n\nexport interface DataConnectSingleEntity {\n  entityId: string;\n}\n\nexport type DataConnectExtension = {\n  path: Array<string | number>;\n} & (DataConnectEntityArray | DataConnectSingleEntity);\n\n/** @internal */\nexport interface DataConnectMaxAge {\n  maxAge: string;\n}\n\n/** @internal */\nexport type DataConnectExtensionWithMaxAge = {\n  path: Array<string | number>;\n} & (DataConnectEntityArray | DataConnectSingleEntity | DataConnectMaxAge);\n\nexport interface Extensions {\n  dataConnect?: DataConnectExtension[];\n}\n\n/** @internal */\nexport interface ExtensionsWithMaxAge {\n  dataConnect?: DataConnectExtensionWithMaxAge[];\n}\n\n/** @internal */\nexport interface DataConnectResponse<T> {\n  data: T;\n  errors: Error[];\n  extensions: Extensions;\n}\n\n/** @internal */\nexport interface DataConnectResponseWithMaxAge<T> {\n  data: T;\n  errors: Error[];\n  extensions: ExtensionsWithMaxAge;\n}\n\n/**\n * Observer defined by the Query Layer for receiving notifications from the Transport Layer.\n * @internal\n */\nexport interface SubscribeObserver<Data> {\n  onData(response: DataConnectResponse<Data>): Promise<void> | void;\n  onDisconnect(code: string, reason: string): void;\n  onError(error: Error): void;\n}\n\n/**\n * Interface defining the external API of the transport layer.\n * @internal\n */\nexport interface DataConnectTransportInterface {\n  /**\n   * Invoke a query execution request.\n   * @param queryName The name of the query to execute.\n   * @param body The variables associated with the query.\n   * @returns A promise resolving to the DataConnectResponse.\n   */\n  invokeQuery<Data, Variables>(\n    queryName: string,\n    body?: Variables\n  ): Promise<DataConnectResponseWithMaxAge<Data>>;\n\n  /**\n   * Invoke a mutation execution request.\n   * @param queryName The name of the mutation to execute.\n   * @param body The variables associated with the mutation.\n   * @returns A promise resolving to the DataConnectResponse.\n   */\n  invokeMutation<Data, Variables>(\n    queryName: string,\n    body?: Variables\n  ): Promise<DataConnectResponse<Data>>;\n\n  /**\n   * Subscribes to a query to receive push notifications of updates.\n   * @param observer the observer passed to the transport layer to notify the query layer of events.\n   * @param queryName The name of the query to subscribe to.\n   * @param body The variables associated with the subscription.\n   */\n  invokeSubscribe<Data, Variables>(\n    observer: SubscribeObserver<Data>,\n    queryName: string,\n    body?: Variables\n  ): void;\n\n  /**\n   * Unsubscribes from an active subscription.\n   * @param queryName The name of the query to unsubscribe from.\n   * @param body The variables associated with the subscription.\n   */\n  invokeUnsubscribe<Variables>(queryName: string, body?: Variables): void;\n\n  /**\n   * Configures the transport to use a local Data Connect emulator.\n   * @param host The host address of the emulator (e.g., '127.0.0.1').\n   * @param port The port number the emulator is listening on.\n   * @param sslEnabled Whether to use SSL (HTTPS/WSS) for the emulator connection.\n   */\n  useEmulator(host: string, port?: number, sslEnabled?: boolean): void;\n\n  /**\n   * Callback invoked when the Firebase Auth token is refreshed or changed. Note that this callback\n   * is called immediately asynchronously when the Auth Provider is initialized to provide\n   * the initial auth state.\n   * @param token The new access token or null if signed out.\n   */\n  onAuthTokenChanged: (token: string | null) => void;\n\n  /**\n   * Internal method to set the SDK type for metrics and logging purposes.\n   * @param callerSdkType The type of SDK making the call (e.g., generated vs base).\n   */\n  _setCallerSdkType(callerSdkType: CallerSdkType): void;\n}\n\n/**\n * Type signature of a transport class constructor.\n * @internal\n */\nexport type TransportClass = new (\n  options: DataConnectOptions,\n  apiKey?: string,\n  appId?: string,\n  authProvider?: AuthTokenProvider,\n  appCheckProvider?: AppCheckTokenProvider,\n  transportOptions?: TransportOptions,\n  _isUsingGen?: boolean,\n  _callerSdkType?: CallerSdkType\n) => DataConnectTransportInterface;\n\n/**\n * Constructs the value for the X-Goog-Api-Client header\n * @internal\n */\nexport function getGoogApiClientValue(\n  isUsingGen: boolean,\n  callerSdkType: CallerSdkType\n): string {\n  let str = 'gl-js/ fire/' + SDK_VERSION;\n  if (\n    callerSdkType !== CallerSdkTypeEnum.Base &&\n    callerSdkType !== CallerSdkTypeEnum.Generated\n  ) {\n    str += ' js/' + callerSdkType.toLowerCase();\n  } else if (isUsingGen || callerSdkType === CallerSdkTypeEnum.Generated) {\n    str += ' js/gen';\n  }\n  return str;\n}\n\n/**\n * The base class for all DataConnectTransportInterface implementations. Handles common logic such as\n * URL construction, auth token management, and emulator usage. Concrete transport implementations\n * should extend this class and implement the abstract {@link DataConnectTransportInterface} methods.\n * @internal\n */\nexport abstract class AbstractDataConnectTransport\n  implements DataConnectTransportInterface\n{\n  protected _host = '';\n  protected _port: number | undefined;\n  protected _location = 'l';\n  protected _connectorName = '';\n  /** The resource path for requests from this Data Connect instance. */\n  protected _connectorResourcePath: string;\n  protected _secure = true;\n  protected _project = 'p';\n  protected _serviceName: string;\n  protected _authToken: string | null = null;\n  protected _appCheckToken: string | null | undefined = null;\n  protected _lastToken: string | null = null;\n  protected _isUsingEmulator = false;\n\n  constructor(\n    options: DataConnectOptions,\n    protected apiKey?: string | undefined,\n    protected appId?: string | null,\n    protected authProvider?: AuthTokenProvider | undefined,\n    protected appCheckProvider?: AppCheckTokenProvider | undefined,\n    transportOptions?: TransportOptions | undefined,\n    protected _isUsingGen = false,\n    protected _callerSdkType: CallerSdkType = CallerSdkTypeEnum.Base\n  ) {\n    if (transportOptions) {\n      if (typeof transportOptions.port === 'number') {\n        this._port = transportOptions.port;\n      }\n      if (typeof transportOptions.sslEnabled !== 'undefined') {\n        this._secure = transportOptions.sslEnabled;\n      }\n      this._host = transportOptions.host;\n    }\n    const { location, projectId: project, connector, service } = options;\n    if (location) {\n      this._location = location;\n    }\n    if (project) {\n      this._project = project;\n    }\n    this._serviceName = service;\n    if (!connector) {\n      throw new DataConnectError(\n        Code.INVALID_ARGUMENT,\n        'Connector Name required!'\n      );\n    }\n    this._connectorName = connector;\n    this._connectorResourcePath = `projects/${this._project}/locations/${this._location}/services/${this._serviceName}/connectors/${this._connectorName}`;\n    this.authProvider?.addTokenChangeListener(token => {\n      logDebug(`New Token Available: ${token}`);\n      this.onAuthTokenChanged(token);\n    });\n    this.appCheckProvider?.addTokenChangeListener(result => {\n      const { token } = result;\n      logDebug(`New App Check Token Available: ${token}`);\n      this._appCheckToken = token;\n    });\n  }\n\n  /** Get the endpoint URL this transport should use to communicate with the backend. */\n  abstract get endpointUrl(): string;\n\n  useEmulator(host: string, port?: number, isSecure?: boolean): void {\n    this._host = host;\n    this._isUsingEmulator = true;\n    if (typeof port === 'number') {\n      this._port = port;\n    }\n    if (typeof isSecure !== 'undefined') {\n      this._secure = isSecure;\n    }\n  }\n\n  async getWithAuth(forceToken = false): Promise<string | null> {\n    let starterPromise: Promise<string | null> = new Promise(resolve =>\n      resolve(this._authToken)\n    );\n    if (this.appCheckProvider) {\n      const appCheckToken = await this.appCheckProvider.getToken();\n      if (appCheckToken) {\n        this._appCheckToken = appCheckToken.token;\n      }\n    }\n    if (this.authProvider) {\n      starterPromise = this.authProvider\n        .getToken(/*forceToken=*/ forceToken)\n        .then(data => {\n          if (!data) {\n            return null;\n          }\n          this._authToken = data.accessToken;\n          return this._authToken;\n        });\n    } else {\n      starterPromise = new Promise(resolve => resolve(''));\n    }\n    return starterPromise;\n  }\n\n  async withRetry<T>(\n    promiseFactory: () => Promise<DataConnectResponse<T>>,\n    retry = false\n  ): Promise<DataConnectResponse<T>> {\n    let isNewToken = false;\n    return this.getWithAuth(retry)\n      .then(res => {\n        isNewToken = this._lastToken !== res;\n        this._lastToken = res;\n        return res;\n      })\n      .then(promiseFactory)\n      .catch(err => {\n        // Only retry if the result is unauthorized and the last token isn't the same as the new one.\n        if (\n          'code' in err &&\n          err.code === Code.UNAUTHORIZED &&\n          !retry &&\n          isNewToken\n        ) {\n          logDebug('Retrying due to unauthorized');\n          return this.withRetry(promiseFactory, true);\n        }\n        throw err;\n      });\n  }\n\n  _setLastToken(lastToken: string | null): void {\n    this._lastToken = lastToken;\n  }\n\n  abstract invokeQuery<Data, Variables>(\n    queryName: string,\n    body?: Variables\n  ): Promise<DataConnectResponseWithMaxAge<Data>>;\n\n  abstract invokeMutation<Data, Variables>(\n    queryName: string,\n    body?: Variables\n  ): Promise<DataConnectResponse<Data>>;\n\n  abstract invokeSubscribe<Data, Variables>(\n    observer: SubscribeObserver<Data>,\n    queryName: string,\n    body?: Variables\n  ): void;\n\n  abstract invokeUnsubscribe<Variables>(\n    queryName: string,\n    variables: Variables\n  ): void;\n\n  abstract onAuthTokenChanged(newToken: string | null): void;\n\n  _setCallerSdkType(callerSdkType: CallerSdkType): void {\n    this._callerSdkType = callerSdkType;\n  }\n}\n","/**\n * @license\n * Copyright 2024 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { isCloudWorkstation } from '@firebase/util';\n\nimport {\n  CallerSdkType,\n  CallerSdkTypeEnum,\n  DataConnectResponse,\n  Extensions\n} from '..';\nimport {\n  Code,\n  DataConnectError,\n  DataConnectOperationError,\n  DataConnectOperationFailureResponse\n} from '../../core/error';\nimport { SDK_VERSION } from '../../core/version';\nimport { logError } from '../../logger';\n\n/** The fetch implementation to be used by the {@link RESTTransport}. */\nlet connectFetch: typeof fetch | null = globalThis.fetch;\n\n/**\n * This function is ONLY used for testing and for ensuring compatability in environments which may\n * be using a poyfill and/or bundlers. It should not be called by users of the Firebase JS SDK.\n * @internal\n */\nexport function initializeFetch(fetchImpl: typeof fetch): void {\n  connectFetch = fetchImpl;\n}\n\nfunction getGoogApiClientValue(\n  _isUsingGen: boolean,\n  _callerSdkType: CallerSdkType\n): string {\n  let str = 'gl-js/ fire/' + SDK_VERSION;\n  if (\n    _callerSdkType !== CallerSdkTypeEnum.Base &&\n    _callerSdkType !== CallerSdkTypeEnum.Generated\n  ) {\n    str += ' js/' + _callerSdkType.toLowerCase();\n  } else if (_isUsingGen || _callerSdkType === CallerSdkTypeEnum.Generated) {\n    str += ' js/gen';\n  }\n  return str;\n}\nexport interface DataConnectFetchBody<Variables> {\n  name: string;\n  operationName: string;\n  variables: Variables;\n}\nexport async function dcFetch<Data, Variables>(\n  url: string,\n  body: DataConnectFetchBody<Variables>,\n  { signal }: AbortController,\n  appId: string | null | undefined,\n  accessToken: string | null,\n  appCheckToken: string | null | undefined,\n  _isUsingGen: boolean,\n  _callerSdkType: CallerSdkType,\n  _isUsingEmulator: boolean\n): Promise<DataConnectResponse<Data>> {\n  if (!connectFetch) {\n    throw new DataConnectError(Code.OTHER, 'No Fetch Implementation detected!');\n  }\n  const headers: HeadersInit = {\n    'Content-Type': 'application/json',\n    'X-Goog-Api-Client': getGoogApiClientValue(_isUsingGen, _callerSdkType)\n  };\n  if (accessToken) {\n    headers['X-Firebase-Auth-Token'] = accessToken;\n  }\n  if (appId) {\n    headers['x-firebase-gmpid'] = appId;\n  }\n  if (appCheckToken) {\n    headers['X-Firebase-AppCheck'] = appCheckToken;\n  }\n  const bodyStr = JSON.stringify(body);\n  const fetchOptions: RequestInit = {\n    body: bodyStr,\n    method: 'POST',\n    headers,\n    signal\n  };\n  if (isCloudWorkstation(url) && _isUsingEmulator) {\n    fetchOptions.credentials = 'include';\n  }\n\n  let response: Response;\n  try {\n    response = await connectFetch(url, fetchOptions);\n  } catch (err) {\n    const message =\n      err && typeof err === 'object' && 'message' in err\n        ? (err as unknown as Record<string, unknown>)['message']\n        : String(err);\n    throw new DataConnectError(Code.OTHER, 'Failed to fetch: ' + message);\n  }\n  let jsonResponse: JsonResponse<Data>;\n  try {\n    jsonResponse = await response.json();\n  } catch (e) {\n    const message =\n      e && typeof e === 'object' && 'message' in e\n        ? (e as unknown as Record<string, unknown>)['message']\n        : String(e);\n    throw new DataConnectError(\n      Code.OTHER,\n      'Failed to parse JSON response: ' + message\n    );\n  }\n  const message = getErrorMessage(jsonResponse);\n  if (response.status >= 400) {\n    logError('Error while performing request: ' + JSON.stringify(jsonResponse));\n    if (response.status === 401) {\n      throw new DataConnectError(Code.UNAUTHORIZED, message);\n    }\n    throw new DataConnectError(Code.OTHER, message);\n  }\n  if (jsonResponse.errors && jsonResponse.errors.length) {\n    const stringified = JSON.stringify(jsonResponse.errors);\n    const failureResponse: DataConnectOperationFailureResponse = {\n      errors: jsonResponse.errors,\n      data: jsonResponse.data as Record<string, unknown>\n    };\n    throw new DataConnectOperationError(\n      'DataConnect error while performing request: ' + stringified,\n      failureResponse\n    );\n  }\n  if (!jsonResponse.extensions) {\n    jsonResponse.extensions = {\n      dataConnect: []\n    };\n  }\n  return jsonResponse as DataConnectResponse<Data>;\n}\ninterface JsonResponse<Data> {\n  message?: string;\n  errors: [];\n  data: Record<string, unknown> | Data | null;\n  extensions?: Extensions;\n}\nfunction getErrorMessage(obj: JsonResponse<unknown>): string {\n  if ('message' in obj && obj.message) {\n    return obj.message;\n  }\n  return JSON.stringify(obj);\n}\n","/**\n * @license\n * Copyright 2024 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { DataConnectOptions, TransportOptions } from '../api/DataConnect';\nimport { Code, DataConnectError } from '../core/error';\nimport { logError } from '../logger';\n\nexport const PROD_HOST = 'firebasedataconnect.googleapis.com';\nexport const WEBSOCKET_PATH =\n  'ws/google.firebase.dataconnect.v1.ConnectorStreamService';\n\nexport function restUrlBuilder(\n  projectConfig: DataConnectOptions,\n  transportOptions: TransportOptions\n): string {\n  const { connector, location, projectId: project, service } = projectConfig;\n  const { host, sslEnabled, port } = transportOptions;\n  const protocol = sslEnabled ? 'https' : 'http';\n  const realHost = host || PROD_HOST;\n  let baseUrl = `${protocol}://${realHost}`;\n  if (typeof port === 'number') {\n    baseUrl += `:${port}`;\n  } else if (typeof port !== 'undefined') {\n    logError('Port type is of an invalid type');\n    throw new DataConnectError(\n      Code.INVALID_ARGUMENT,\n      'Incorrect type for port passed in!'\n    );\n  }\n  return `${baseUrl}/v1/projects/${project}/locations/${location}/services/${service}/connectors/${connector}`;\n}\n\nexport function websocketUrlBuilder(\n  projectConfig: DataConnectOptions,\n  transportOptions: TransportOptions\n): string {\n  const { location } = projectConfig;\n  const { host, sslEnabled, port } = transportOptions;\n  const protocol = sslEnabled ? 'wss' : 'ws';\n  const realHost = host || PROD_HOST;\n  let baseUrl = `${protocol}://${realHost}`;\n  if (typeof port === 'number') {\n    baseUrl += `:${port}`;\n  } else if (typeof port !== 'undefined') {\n    logError('Port type is of an invalid type');\n    throw new DataConnectError(\n      Code.INVALID_ARGUMENT,\n      'Incorrect type for port passed in!'\n    );\n  }\n  return `${baseUrl}/${WEBSOCKET_PATH}/Connect/locations/${location}`;\n}\n\nexport function addToken(url: string, apiKey?: string): string {\n  if (!apiKey) {\n    return url;\n  }\n  const newUrl = new URL(url);\n  newUrl.searchParams.append('key', apiKey);\n  return newUrl.toString();\n}\n","/**\n * @license\n * Copyright 2024 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n  CallerSdkType,\n  CallerSdkTypeEnum,\n  DataConnectResponse,\n  DataConnectResponseWithMaxAge,\n  AbstractDataConnectTransport,\n  SubscribeObserver\n} from '..';\nimport { DataConnectOptions, TransportOptions } from '../../api/DataConnect';\nimport { AppCheckTokenProvider } from '../../core/AppCheckTokenProvider';\nimport { Code, DataConnectError } from '../../core/error';\nimport { AuthTokenProvider } from '../../core/FirebaseAuthProvider';\nimport { addToken, restUrlBuilder } from '../../util/url';\n\nimport { dcFetch } from './fetch';\n\n/**\n * Fetch-based REST implementation of {@link AbstractDataConnectTransport}.\n * @internal\n */\nexport class RESTTransport extends AbstractDataConnectTransport {\n  constructor(\n    options: DataConnectOptions,\n    apiKey?: string | undefined,\n    appId?: string | null,\n    authProvider?: AuthTokenProvider | undefined,\n    appCheckProvider?: AppCheckTokenProvider | undefined,\n    transportOptions?: TransportOptions | undefined,\n    _isUsingGen = false,\n    _callerSdkType: CallerSdkType = CallerSdkTypeEnum.Base\n  ) {\n    super(\n      options,\n      apiKey,\n      appId,\n      authProvider,\n      appCheckProvider,\n      transportOptions,\n      _isUsingGen,\n      _callerSdkType\n    );\n  }\n\n  get endpointUrl(): string {\n    return restUrlBuilder(\n      {\n        connector: this._connectorName,\n        location: this._location,\n        projectId: this._project,\n        service: this._serviceName\n      },\n      {\n        host: this._host,\n        sslEnabled: this._secure,\n        port: this._port\n      }\n    );\n  }\n\n  invokeQuery: <Data, Variables>(\n    queryName: string,\n    body?: Variables\n  ) => Promise<DataConnectResponseWithMaxAge<Data>> = <\n    Data,\n    Variables = unknown\n  >(\n    queryName: string,\n    body: Variables\n  ) => {\n    const abortController = new AbortController();\n\n    // TODO(mtewani): Update to proper value\n    const withAuth = this.withRetry(() =>\n      dcFetch<Data, Variables>(\n        addToken(`${this.endpointUrl}:executeQuery`, this.apiKey),\n        {\n          name: this._connectorResourcePath,\n          operationName: queryName,\n          variables: body\n        },\n        abortController,\n        this.appId,\n        this._authToken,\n        this._appCheckToken,\n        this._isUsingGen,\n        this._callerSdkType,\n        this._isUsingEmulator\n      )\n    );\n    return withAuth;\n  };\n\n  invokeMutation: <Data, Variables>(\n    queryName: string,\n    body?: Variables\n  ) => Promise<DataConnectResponse<Data>> = <Data, Variables = unknown>(\n    mutationName: string,\n    body: Variables\n  ) => {\n    const abortController = new AbortController();\n    const taskResult = this.withRetry(() => {\n      return dcFetch<Data, Variables>(\n        addToken(`${this.endpointUrl}:executeMutation`, this.apiKey),\n        {\n          name: this._connectorResourcePath,\n          operationName: mutationName,\n          variables: body\n        },\n        abortController,\n        this.appId,\n        this._authToken,\n        this._appCheckToken,\n        this._isUsingGen,\n        this._callerSdkType,\n        this._isUsingEmulator\n      );\n    });\n    return taskResult;\n  };\n\n  invokeSubscribe<Data, Variables>(\n    observer: SubscribeObserver<Data>,\n    queryName: string,\n    body?: Variables\n  ): void {\n    throw new DataConnectError(\n      Code.NOT_SUPPORTED,\n      'Subscriptions are not supported using REST!'\n    );\n  }\n\n  invokeUnsubscribe<Variables>(queryName: string, body?: Variables): void {\n    throw new DataConnectError(\n      Code.NOT_SUPPORTED,\n      'Unsubscriptions are not supported using REST!'\n    );\n  }\n\n  onAuthTokenChanged(newToken: string | null): void {\n    this._authToken = newToken;\n  }\n}\n","/**\n * @license\n * Copyright 2026 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { FirebaseError } from '@firebase/util';\n\nimport { DataConnectOptions, TransportOptions } from '../../api/DataConnect';\nimport { AppCheckTokenProvider } from '../../core/AppCheckTokenProvider';\nimport {\n  Code,\n  DataConnectError,\n  DataConnectOperationError,\n  DataConnectOperationFailureResponse\n} from '../../core/error';\nimport { AuthTokenProvider } from '../../core/FirebaseAuthProvider';\nimport { logError, logDebug } from '../../logger';\nimport {\n  AbstractDataConnectTransport,\n  CallerSdkType,\n  CallerSdkTypeEnum,\n  DataConnectResponse,\n  SubscribeObserver,\n  getGoogApiClientValue\n} from '../transport';\n\nimport {\n  CancelStreamRequest,\n  DataConnectStreamRequest,\n  ExecuteStreamRequest,\n  ResumeStreamRequest,\n  StreamRequestHeaders,\n  SubscribeStreamRequest\n} from './wire';\n\n/** The Request ID of the first request over the stream */\nconst FIRST_REQUEST_ID = 1;\n\n/** Time to wait before closing an idle connection (no active subscriptions). */\nconst IDLE_CONNECTION_TIMEOUT_MS = 60 * 1000; // 1 minute\n\n/** Initial reconnect delay in ms */\nconst INITIAL_RECONNECT_DELAY_MS = 1000;\n/** Max reconnect delay in ms */\nconst MAX_RECONNECT_DELAY_MS = 30000;\n/** Max random jitter to add to reconnect delay in ms */\nconst MAX_RECONNECT_JITTER_MS = 500;\n/** Factor to multiply delay by on failure */\nconst RECONNECT_BACKOFF_FACTOR = 1.3;\n/** Max number of reconnection attempts before giving up */\nconst MAX_RECONNECT_ATTEMPTS = 10;\n\n/**\n * A promise returned to the user when invoking an operation via {@linkcode AbstractDataConnectStreamTransport.invokeQuery | invokeQuery}\n * or {@linkcode AbstractDataConnectStreamTransport.invokeMutation | invokeMutation} and the functions\n * that resolve/reject it.\n * @internal\n */\nexport interface InvokeOperationPromise<Data> {\n  responsePromise: Promise<DataConnectResponse<Data>>;\n  resolveFn: (response: DataConnectResponse<Data>) => void;\n  // eslint-disable-next-line @typescript-eslint/no-explicit-any\n  rejectFn: (reason: any) => void;\n}\n\n/**\n * The base class for all Stream Transport implementations.\n * Handles management of logical streams (requests), authentication, data routing to query layer,\n * request optimizations, etc.\n * @internal\n */\nexport abstract class AbstractDataConnectStreamTransport extends AbstractDataConnectTransport {\n  /** Optional callback invoked when the stream closes (gracefully or fatally). */\n  onCloseCallback?: () => void;\n\n  /** True if the physical stream connection is fully open and ready to transmit data. */\n  abstract get streamIsReady(): boolean;\n\n  /** Is the stream currently waiting to close connection? */\n  get isPendingClose(): boolean {\n    return !!this.idleTimeout;\n  }\n\n  /** True if the transport is unable to connect to the server */\n  isUnableToConnect = false;\n\n  /** True if there are active subscriptions on the stream */\n  get hasActiveSubscriptions(): boolean {\n    return this.activeInvokeSubscribeRequests.size > 0;\n  }\n\n  /** True if there are active execute or mutation requests on the stream */\n  get hasActiveExecuteRequests(): boolean {\n    return (\n      this.activeInvokeQueryRequests.size > 0 ||\n      this.activeInvokeMutationRequests.size > 0\n    );\n  }\n\n  constructor(\n    options: DataConnectOptions,\n    protected apiKey?: string | undefined,\n    protected appId?: string | null,\n    protected authProvider?: AuthTokenProvider | undefined,\n    protected appCheckProvider?: AppCheckTokenProvider | undefined,\n    transportOptions?: TransportOptions | undefined,\n    protected _isUsingGen = false,\n    protected _callerSdkType: CallerSdkType = CallerSdkTypeEnum.Base\n  ) {\n    super(\n      options,\n      apiKey,\n      appId,\n      authProvider,\n      appCheckProvider,\n      transportOptions,\n      _isUsingGen,\n      _callerSdkType\n    );\n\n    this.registerBrowserEventListeners();\n  }\n\n  /**\n   * Register event listeners for browser-specific events like online/offline and visibility changes.\n   */\n  private registerBrowserEventListeners(): void {\n    if ('addEventListener' in globalThis) {\n      const listener = this.onOnlineEventListener;\n      globalThis.addEventListener('online', listener);\n      this.removeOnlineEventListener = () =>\n        globalThis.removeEventListener('online', listener);\n    }\n\n    const doc = globalThis.document;\n    if (doc && 'addEventListener' in doc) {\n      const listener = this.onVisibilityChangeEventListener;\n      doc.addEventListener('visibilitychange', listener);\n      this.removeVisibilityChangeEventListener = () =>\n        doc.removeEventListener('visibilitychange', listener);\n    }\n  }\n\n  /**\n   * Remove event listeners registered by {@linkcode AbstractDataConnectStreamTransport.registerBrowserEventListeners | registerBrowserEventListeners()}\n   * for browser-specific events like online/offline and visibility changes.\n   */\n  private cleanupBrowserEventListeners(): void {\n    this.removeVisibilityChangeEventListener?.();\n    this.removeVisibilityChangeEventListener = null;\n    this.removeOnlineEventListener?.();\n    this.removeOnlineEventListener = null;\n  }\n\n  /**\n   * Disposes of the transport instance, cleaning up event listeners and timers,\n   * and closing the connection.\n   */\n  async cleanupAndTerminate(code?: Code, reason?: string): Promise<void> {\n    this.cleanupBrowserEventListeners();\n    this.cancelReconnect();\n    this.cancelClose();\n    this.rejectAllRequests(code ?? Code.OTHER, reason ?? 'Stream disposed.');\n    await this.closeConnection();\n    this.onCloseCallback?.();\n  }\n\n  /**\n   * Open a physical connection to the server.\n   * @returns a promise which resolves when the connection is ready, or rejects if it fails to open.\n   */\n  protected abstract openConnection(): Promise<void>;\n\n  /**\n   * Close the physical connection with the server. Handles no cleanup - simply closes the\n   * implementation-specific connection. On failure to close, the connection is still considered closed.\n   * @returns a promise which resolves when the connection is closed, or rejects if it fails to close.\n   */\n  protected abstract closeConnection(): Promise<void>;\n\n  /**\n   * Queue a {@linkcode DataConnectStreamRequest} to be sent over the stream.\n   * @param requestBody The body of the message to be sent.\n   * @throws DataConnectError if sending fails.\n   */\n  protected abstract sendMessage<Variables>(\n    requestBody: DataConnectStreamRequest<Variables>\n  ): Promise<void>;\n\n  /**\n   * Ensures that that there is an open connection. If there is none, it initiates a new one.\n   * If a connection attempt is already in progress, it returns the existing connection promise.\n   * @returns A promise that resolves when the stream is open and ready.\n   */\n  protected abstract ensureConnection(): Promise<void>;\n\n  /** The Request ID of the next message to be sent. Monotonically increasing sequence number starting at {@linkcode FIRST_REQUEST_ID}. */\n  private requestNumber = FIRST_REQUEST_ID;\n  /**\n   * Generates and returns the next Request ID. Starts at {@linkcode FIRST_REQUEST_ID} and increments\n   * for each request sent.\n   */\n  private nextRequestId(): string {\n    return (this.requestNumber++).toString();\n  }\n\n  /**\n   * Map of query/variables to their active {@linkcode ExecuteStreamRequest} or {@linkcode ResumeStreamRequest}\n   * request bodies. These requests are de-duplicated by query/variables so that there is only one active\n   * request for each query/variables combination.\n   */\n  private activeInvokeQueryRequests = new Map<\n    string,\n    ExecuteStreamRequest<unknown> | ResumeStreamRequest\n  >();\n\n  /**\n   * Map of query/variables to the promises returned to the user, for invokeQuery requests which are\n   * queued and waiting for active request to resolve.\n   */\n  private queuedInvokeQueryRequests = new Map<\n    string,\n    // eslint-disable-next-line @typescript-eslint/no-explicit-any\n    InvokeOperationPromise<any>\n  >();\n\n  /**\n   * Map of mutation/variables to their active {@linkcode ExecuteStreamRequest} request bodies. Mutations\n   * can have more than one active request at a time as they are not idempotent, and therefore should\n   * not be de-duplicated.\n   */\n  private activeInvokeMutationRequests = new Map<\n    string,\n    Array<ExecuteStreamRequest<unknown>>\n  >();\n\n  /**\n   * Map of query/variables to their active {@linkcode SubscribeStreamRequest} request bodies. There\n   * may only be one active request for each query/variables combination.\n   */\n  private activeInvokeSubscribeRequests = new Map<\n    string,\n    SubscribeStreamRequest<unknown>\n  >();\n\n  /**\n   * Map of active {@linkcode ExecuteStreamRequest} RequestIds from {@linkcode invokeQuery} and {@linkcode invokeMutation},\n   * and their corresponding {@linkcode InvokeOperationPromise}.\n   */\n  private executeRequestPromises = new Map<\n    string,\n    // eslint-disable-next-line @typescript-eslint/no-explicit-any\n    InvokeOperationPromise<any>\n  >();\n\n  /**\n   * Map of active {@linkcode ResumeStreamRequest} RequestIds from {@linkcode invokeQuery}, and their\n   * corresponding {@linkcode InvokeOperationPromise}.\n   */\n  private resumeRequestPromises = new Map<\n    string,\n    // eslint-disable-next-line @typescript-eslint/no-explicit-any\n    InvokeOperationPromise<any>\n  >();\n\n  /**\n   * Map of active {@linkcode invokeSubscribe} RequestIds and their corresponding {@linkcode SubscribeObserver}.\n   */\n  private subscribeObservers = new Map<string, SubscribeObserver<unknown>>();\n\n  /**\n   * Map of subscribe RequestIds to deferred unsubscription requests. Used when a client unsubscribes\n   * while a resume request is actively pending.\n   */\n  private pendingCancellations = new Map<\n    string,\n    { operationName: string; variables: unknown }\n  >();\n\n  /** current idle timeout, if any */\n  private idleTimeout: ReturnType<typeof setTimeout> | null = null;\n\n  /** current auth uid. used to detect if a different user logs in */\n  private authUid: string | null | undefined;\n  /** Flag to ensure we wait for the initial auth state once per connection attempt. */\n  private hasWaitedForInitialAuth = false;\n\n  /**\n   * Tracks an {@linkcode invokeMutation} request, storing the request body and creating and storing a\n   * response promise that will be resolved when the response is received.\n   * @returns The tracked {@linkcode InvokeOperationPromise}.\n   *\n   * @remarks\n   * This method returns a promise, but is synchronous.\n   */\n  private trackInvokeMutationRequest<Data>(\n    requestId: string,\n    mapKey: string,\n    executeBody: ExecuteStreamRequest<unknown>\n  ): InvokeOperationPromise<Data> {\n    let resolveFn: (response: DataConnectResponse<Data>) => void;\n    // eslint-disable-next-line @typescript-eslint/no-explicit-any\n    let rejectFn: (reason: any) => void;\n    const responsePromise = new Promise<DataConnectResponse<Data>>(\n      (resolve, reject) => {\n        resolveFn = resolve;\n        rejectFn = reject;\n      }\n    );\n    const executeRequestPromise: InvokeOperationPromise<Data> = {\n      responsePromise,\n      resolveFn: resolveFn!,\n      rejectFn: rejectFn!\n    };\n\n    const activeRequests = this.activeInvokeMutationRequests.get(mapKey) || [];\n    activeRequests.push(executeBody);\n    this.activeInvokeMutationRequests.set(mapKey, activeRequests);\n    this.executeRequestPromises.set(requestId, executeRequestPromise);\n\n    return executeRequestPromise;\n  }\n\n  /**\n   * Tracks an {@linkcode invokeSubscribe} request, storing the request body and the {@linkcode SubscribeObserver}.\n   * @remarks\n   * This method is synchronous.\n   */\n  private trackInvokeSubscribeRequest<Data>(\n    requestId: string,\n    mapKey: string,\n    subscribeBody: SubscribeStreamRequest<unknown>,\n    observer: SubscribeObserver<Data>\n  ): void {\n    this.activeInvokeSubscribeRequests.set(mapKey, subscribeBody);\n    this.subscribeObservers.set(requestId, observer);\n  }\n\n  /**\n   * Cleans up the query execute request tracking data structures, deleting the tracked request and\n   * it's associated promise.\n   */\n  private cleanupInvokeQueryRequest(requestId: string, mapKey: string): void {\n    this.activeInvokeQueryRequests.delete(mapKey);\n    this.executeRequestPromises.delete(requestId);\n    this.resumeRequestPromises.delete(requestId);\n  }\n\n  /**\n   * Cleans up the mutation execute request tracking data structures, deleting the tracked request and\n   * it's associated promise.\n   */\n  private cleanupInvokeMutationRequest(\n    requestId: string,\n    mapKey: string\n  ): void {\n    const executeRequests = this.activeInvokeMutationRequests.get(mapKey);\n    if (executeRequests) {\n      const updatedRequests = executeRequests.filter(\n        request => request.requestId !== requestId\n      );\n      if (updatedRequests.length > 0) {\n        this.activeInvokeMutationRequests.set(mapKey, updatedRequests);\n      } else {\n        this.activeInvokeMutationRequests.delete(mapKey);\n      }\n    }\n    this.executeRequestPromises.delete(requestId);\n  }\n\n  /**\n   * Cleans up the subscribe request tracking data structures, deleting the tracked request and\n   * it's associated promise.\n   */\n  private cleanupInvokeSubscribeRequest(\n    requestId: string,\n    mapKey: string\n  ): void {\n    this.activeInvokeSubscribeRequests.delete(mapKey);\n    this.subscribeObservers.delete(requestId);\n  }\n\n  /** Delay for next reconnection attempt in ms */\n  private reconnectDelayMs = INITIAL_RECONNECT_DELAY_MS;\n  /** Timer for reconnection */\n  private reconnectTimer: ReturnType<typeof setTimeout> | null = null;\n  /** Number of consecutive reconnection attempts */\n  private reconnectAttempts = 0;\n\n  /** Callback to remove online event listener */\n  private removeOnlineEventListener: (() => void) | null = null;\n  /** Callback to remove visibility change event listener */\n  private removeVisibilityChangeEventListener: (() => void) | null = null;\n\n  /**\n   * Short-circuit a reconnection attempt, if one is pending. Triggered when an online event is\n   * dispatched.\n   */\n  onOnlineEventListener = (): void => {\n    if (this.reconnectTimer) {\n      this.cancelReconnect();\n      void this.attemptReconnect();\n    }\n  };\n\n  /**\n   * Short-circuit a reconnection attempt, if one is pending. Triggered when a visibility change\n   * event is dispatched.\n   */\n  onVisibilityChangeEventListener = (): void => {\n    const doc = globalThis.document;\n    if (doc && doc.visibilityState === 'visible' && this.reconnectTimer) {\n      this.cancelReconnect();\n      void this.attemptReconnect();\n    }\n  };\n\n  /**\n   * Cancel reconnecting.\n   */\n  private cancelReconnect(): void {\n    if (this.reconnectTimer) {\n      clearTimeout(this.reconnectTimer);\n      this.reconnectTimer = null;\n    }\n  }\n\n  /**\n   * Starts the backoff timer for reconnection attempts. We use an exponential backoff with randomized\n   * jitter to prevent overwhelming the backend with connection attempts.\n   */\n  private startReconnectBackoff(): void {\n    if (this.reconnectTimer) {\n      return;\n    }\n    if (this.reconnectAttempts++ >= MAX_RECONNECT_ATTEMPTS) {\n      const errorString =\n        'Stream disconnected and could not reconnect - max stream reconnection attempts reached.';\n      logError(errorString);\n      void this.cleanupAndTerminate(Code.OTHER, errorString);\n      return;\n    }\n    const delay = this.reconnectDelayMs;\n    this.reconnectDelayMs = Math.min(\n      this.reconnectDelayMs * RECONNECT_BACKOFF_FACTOR,\n      MAX_RECONNECT_DELAY_MS\n    );\n    const jitter = Math.random() * MAX_RECONNECT_JITTER_MS;\n\n    this.reconnectTimer = setTimeout(() => {\n      this.reconnectTimer = null;\n      void this.attemptReconnect();\n    }, delay + jitter);\n  }\n\n  private async attemptReconnect(): Promise<void> {\n    try {\n      await this.ensureConnection();\n      // reset on success\n      this.reconnectDelayMs = INITIAL_RECONNECT_DELAY_MS;\n      this.reconnectAttempts = 0;\n      await this.retriggerActiveRequests();\n    } catch (e) {\n      if (e instanceof FirebaseError) {\n        logDebug(\n          `Reconnect attempt #${this.reconnectAttempts} failed with Firebase error: ${e.message}. Retrying...`\n        );\n        this.startReconnectBackoff();\n      } else {\n        logError(\n          `Unexpected error during reconnect attempt #${this.reconnectAttempts}: ${e}`\n        );\n        void this.cleanupAndTerminate(\n          Code.OTHER,\n          `Unexpected error during reconnect attempt #${this.reconnectAttempts}: ${e}`\n        );\n      }\n    }\n  }\n\n  /**\n   * Retriggers all active requests on the stream connection - first subscribes, then query executions,\n   * and skip mutations. Used after a successful reconnection.\n   */\n  private async retriggerActiveRequests(): Promise<void> {\n    for (const [_, subscribeBody] of this.activeInvokeSubscribeRequests) {\n      await this.sendRequestMessage(subscribeBody);\n    }\n    for (const [_, requestBody] of this.activeInvokeQueryRequests) {\n      await this.sendRequestMessage(requestBody);\n    }\n  }\n\n  /**\n   * Tracks if the next message to be sent is the first message of the stream.\n   */\n  private isFirstStreamMessage = true;\n\n  /**\n   * Tracks the last auth token sent to the server.\n   * Used to detect if the token has changed and needs to be resent.\n   */\n  private lastSentAuthToken: string | null = null;\n\n  /**\n   * Indicates whether we should include the auth token in the next message.\n   * Only true if there is an auth token and it is different from the last sent auth token, or this\n   * is the first message.\n   */\n  private get shouldIncludeAuth(): boolean {\n    return (\n      this.isFirstStreamMessage ||\n      (!!this._authToken && this._authToken !== this.lastSentAuthToken)\n    );\n  }\n\n  /**\n   * Called by the concrete transport implementation when the physical connection is ready.\n   */\n  protected onConnectionReady(): void {\n    this.isFirstStreamMessage = true;\n    this.lastSentAuthToken = null;\n    this.hasWaitedForInitialAuth = false;\n  }\n\n  /**\n   * Begin closing the connection. Waits for {@linkcode IDLE_CONNECTION_TIMEOUT_MS} without cleaning up\n   * any requests (meaning it will not close after the timeout unless the requests are closed first).\n   * This is a graceful close - it will be called when there are no more active subscriptions, so\n   * there's no need to cleanup.\n   */\n  private startIdleCloseTimeout(): void {\n    if (this.idleTimeout) {\n      return;\n    }\n    this.idleTimeout = setTimeout(() => {\n      this.idleTimeout = null;\n      // Safety check: Don't close if new requests arrived during the timeout!\n      if (this.hasActiveSubscriptions || this.hasActiveExecuteRequests) {\n        return;\n      }\n      void this.cleanupAndTerminate(\n        Code.OTHER,\n        'Stream closed due to idleness.'\n      );\n    }, IDLE_CONNECTION_TIMEOUT_MS);\n  }\n\n  /**\n   * Cancel closing the connection.\n   */\n  private cancelClose(): void {\n    if (this.idleTimeout) {\n      clearTimeout(this.idleTimeout);\n      this.idleTimeout = null;\n    }\n  }\n\n  /**\n   * Reject all active execute promises and notify all subscribe observers with the given error.\n   * Clear active request tracking maps without cancelling or re-invoking any requests.\n   */\n  private rejectAllRequests(code: Code, reason: string): void {\n    this.activeInvokeQueryRequests.clear();\n    this.activeInvokeMutationRequests.clear();\n    this.activeInvokeSubscribeRequests.clear();\n\n    const error = new DataConnectError(code, reason);\n    for (const [mapKey, { rejectFn }] of this.queuedInvokeQueryRequests) {\n      this.queuedInvokeQueryRequests.delete(mapKey);\n      rejectFn(error);\n    }\n    for (const [requestId, { rejectFn }] of this.executeRequestPromises) {\n      this.executeRequestPromises.delete(requestId);\n      rejectFn(error);\n    }\n    for (const [requestId, { rejectFn }] of this.resumeRequestPromises) {\n      this.resumeRequestPromises.delete(requestId);\n      rejectFn(error);\n    }\n    for (const [requestId, observer] of this.subscribeObservers) {\n      this.subscribeObservers.delete(requestId);\n      observer.onDisconnect(code, reason);\n    }\n    this.pendingCancellations.clear();\n    this.cancelReconnect();\n  }\n\n  /**\n   * Reject all mutation execute promises.\n   * Clear active request tracking maps without cancelling or re-invoking any requests.\n   */\n  private rejectAllMutationsOnReconnect(): void {\n    const error = new DataConnectError(\n      Code.OTHER,\n      'Mutation aborted due to stream disconnect.'\n    );\n    for (const [_, requests] of this.activeInvokeMutationRequests) {\n      for (const request of requests) {\n        const promise = this.executeRequestPromises.get(request.requestId);\n        if (promise) {\n          promise.rejectFn(error);\n          this.executeRequestPromises.delete(request.requestId);\n        }\n      }\n    }\n    this.activeInvokeMutationRequests.clear();\n  }\n\n  /**\n   * Called by concrete implementations when the stream is successfully closed, gracefully or otherwise.\n   */\n  protected onStreamClose(code: number, reason: string): void {\n    this.cancelClose();\n    if (!this.hasActiveSubscriptions) {\n      // skip reconnection if there are no active subscriptions\n      void this.cleanupAndTerminate(\n        Code.OTHER,\n        `Stream disconnected while idle with code ${code}: ${reason}`\n      );\n      return;\n    }\n    logDebug(\n      `Stream disconnected with code ${code}: ${reason}. Attempting reconnect...`\n    );\n    this.rejectAllMutationsOnReconnect();\n    this.startReconnectBackoff();\n  }\n\n  /**\n   * Prepares a stream request message by adding necessary headers and metadata.\n   * If this is the first message on the stream, it includes the resource name, auth token, and App Check token.\n   * If the auth token has refreshed since the last message, it includes the new auth token.\n   *\n   * This method is called by the concrete transport implementation before sending a message.\n   *\n   * @returns the requestBody, with attached headers and initial request fields\n   */\n  protected prepareMessage<\n    Variables,\n    StreamBody extends DataConnectStreamRequest<Variables>\n  >(requestBody: StreamBody): StreamBody {\n    const preparedRequestBody: StreamBody = { ...requestBody };\n    const headers: StreamRequestHeaders = {};\n    if (this.appId) {\n      headers['x-firebase-gmpid'] = this.appId;\n    }\n    headers['X-Goog-Api-Client'] = getGoogApiClientValue(\n      this._isUsingGen,\n      this._callerSdkType\n    );\n    if (this.shouldIncludeAuth && this._authToken) {\n      headers['X-Firebase-Auth-Token'] = this._authToken;\n      this.lastSentAuthToken = this._authToken;\n    }\n    if (this.isFirstStreamMessage) {\n      if (this._appCheckToken) {\n        headers['X-Firebase-App-Check'] = this._appCheckToken;\n      }\n      preparedRequestBody.name = this._connectorResourcePath;\n    }\n    preparedRequestBody.headers = headers;\n    this.isFirstStreamMessage = false;\n    return preparedRequestBody;\n  }\n\n  /**\n   * Sends a request message to the server via the concrete implementation.\n   * Ensures the connection is ready and prepares the message before sending.\n   * @returns A promise that resolves when the request message has been sent.\n   */\n  private async sendRequestMessage<Variables>(\n    requestBody: DataConnectStreamRequest<Variables>\n  ): Promise<void> {\n    if (!this.hasWaitedForInitialAuth && this.authProvider) {\n      await this.getWithAuth();\n      this.hasWaitedForInitialAuth = true;\n    }\n    if (this.streamIsReady) {\n      const prepared = this.prepareMessage(requestBody);\n      return this.sendMessage(prepared);\n    }\n    return this.ensureConnection().then(() => {\n      const prepared = this.prepareMessage(requestBody);\n      return this.sendMessage(prepared);\n    });\n  }\n\n  /**\n   * Helper to generate a consistent string key for the request tracking maps.\n   */\n  private getMapKey(operationName: string, variables?: unknown): string {\n    const sortedVariables = this.sortObjectKeys(variables);\n    return JSON.stringify({ operationName, variables: sortedVariables });\n  }\n\n  /**\n   * Recursively sorts the keys of an object.\n   */\n  private sortObjectKeys(obj: unknown): unknown {\n    if (obj === null || typeof obj !== 'object' || Array.isArray(obj)) {\n      return obj;\n    }\n    const sortedObj: Record<string, unknown> = {};\n    Object.keys(obj as Record<string, unknown>)\n      .sort()\n      .forEach(key => {\n        sortedObj[key] = this.sortObjectKeys(\n          (obj as Record<string, unknown>)[key]\n        );\n      });\n    return sortedObj;\n  }\n\n  /**\n   * @inheritdoc\n   * @remarks\n   * This method synchronously updates the request tracking data structures before sending any message.\n   * If any asynchronous functionality is added to this function, it MUST be done in a way that\n   * preserves the synchronous update of the tracking data structures before the method returns.\n   */\n  invokeQuery<Data, Variables>(\n    queryName: string,\n    variables?: Variables\n  ): Promise<DataConnectResponse<Data>> {\n    const mapKey = this.getMapKey(queryName, variables);\n\n    if (this.activeInvokeQueryRequests.has(mapKey)) {\n      return this.queueInvokeQueryRequest(mapKey);\n    }\n\n    return this.executeOrResumeQuery(queryName, variables, mapKey);\n  }\n\n  /**\n   * Queue a new query execute request to be executed after the currently active query execute\n   * request resolves, and track + return a promise associated with the queued request. If there is\n   * already a queued request for this mapKey, return the existing queued request's promise instead.\n   */\n  private queueInvokeQueryRequest<Data>(\n    mapKey: string\n  ): Promise<DataConnectResponse<Data>> {\n    const existingQueued = this.queuedInvokeQueryRequests.get(mapKey);\n    if (existingQueued) {\n      // only queue one request per mapKey - return existing queued request promise\n      return existingQueued.responsePromise;\n    }\n\n    let resolveFn: (response: DataConnectResponse<Data>) => void;\n    // eslint-disable-next-line @typescript-eslint/no-explicit-any\n    let rejectFn: (reason: any) => void;\n    const responsePromise = new Promise<DataConnectResponse<Data>>(\n      (resolve, reject) => {\n        resolveFn = resolve;\n        rejectFn = reject;\n      }\n    );\n\n    this.queuedInvokeQueryRequests.set(mapKey, {\n      responsePromise,\n      resolveFn: resolveFn!,\n      rejectFn: rejectFn!\n    });\n\n    return responsePromise;\n  }\n\n  /**\n   * Executes or resumes a query. Does not check for any active requests which may be overwritten by\n   * this request - this should be handled by the caller.\n   */\n  private executeOrResumeQuery<Data, Variables>(\n    queryName: string,\n    variables: Variables | undefined,\n    mapKey: string,\n    queuedInvokeOperationPromise?: InvokeOperationPromise<Data>\n  ): Promise<DataConnectResponse<Data>> {\n    const activeSubscription = this.activeInvokeSubscribeRequests.get(mapKey);\n\n    let resolveFn: (response: DataConnectResponse<Data>) => void;\n    // eslint-disable-next-line @typescript-eslint/no-explicit-any\n    let rejectFn: (reason: any) => void;\n    let responsePromise: Promise<DataConnectResponse<Data>>;\n\n    // track the existing queued promise if one exists - otherwise create a new one\n    if (queuedInvokeOperationPromise) {\n      resolveFn = queuedInvokeOperationPromise.resolveFn;\n      rejectFn = queuedInvokeOperationPromise.rejectFn;\n      responsePromise = queuedInvokeOperationPromise.responsePromise;\n    } else {\n      responsePromise = new Promise<DataConnectResponse<Data>>(\n        (resolve, reject) => {\n          resolveFn = resolve;\n          rejectFn = reject;\n        }\n      );\n    }\n\n    let requestId: string;\n    let requestBody: ExecuteStreamRequest<Variables> | ResumeStreamRequest;\n\n    if (activeSubscription) {\n      // resume!\n      requestId = activeSubscription.requestId;\n      requestBody = { requestId, resume: {} };\n      this.resumeRequestPromises.set(requestId, {\n        responsePromise,\n        resolveFn: resolveFn!,\n        rejectFn: rejectFn!\n      });\n    } else {\n      // execute!\n      requestId = this.nextRequestId();\n      requestBody = {\n        requestId,\n        execute: { operationName: queryName, variables }\n      };\n      this.executeRequestPromises.set(requestId, {\n        responsePromise,\n        resolveFn: resolveFn!,\n        rejectFn: rejectFn!\n      });\n    }\n\n    this.activeInvokeQueryRequests.set(mapKey, requestBody);\n\n    responsePromise = responsePromise.finally(() => {\n      this.onInvokeQueryRequestFulfilled(\n        queryName,\n        variables,\n        mapKey,\n        requestId\n      );\n    });\n\n    this.sendRequestMessage(requestBody).catch(err => {\n      rejectFn(err);\n    });\n    return responsePromise;\n  }\n\n  /**\n   * When a query invoke request is fulfilled, clean up and trigger the next queued\n   * request if one exists.\n   */\n  private onInvokeQueryRequestFulfilled(\n    queryName: string,\n    variables: unknown,\n    mapKey: string,\n    requestId: string\n  ): void {\n    this.cleanupInvokeQueryRequest(requestId, mapKey);\n\n    const deferredCancel = this.pendingCancellations.get(requestId);\n    if (deferredCancel) {\n      this.pendingCancellations.delete(requestId);\n      this.cancelSubscription(requestId, mapKey);\n    }\n\n    const queuedRequestPromise = this.queuedInvokeQueryRequests.get(mapKey);\n    if (!queuedRequestPromise) {\n      if (!this.hasActiveSubscriptions && !this.hasActiveExecuteRequests) {\n        this.startIdleCloseTimeout();\n      }\n      return;\n    }\n\n    this.queuedInvokeQueryRequests.delete(mapKey);\n\n    void this.executeOrResumeQuery(\n      queryName,\n      variables,\n      mapKey,\n      queuedRequestPromise\n    );\n  }\n\n  /**\n   * @inheritdoc\n   * @remarks\n   * This method synchronously updates the request tracking data structures before sending any message.\n   * If any asynchronous functionality is added to this function, it MUST be done in a way that\n   * preserves the synchronous update of the tracking data structures before the method returns.\n   */\n  invokeMutation<Data, Variables>(\n    mutationName: string,\n    variables?: Variables\n  ): Promise<DataConnectResponse<Data>> {\n    const requestId = this.nextRequestId();\n    const activeRequestKey = { operationName: mutationName, variables };\n    const mapKey = this.getMapKey(mutationName, variables);\n    const executeBody: ExecuteStreamRequest<Variables> = {\n      requestId,\n      execute: activeRequestKey\n    };\n\n    let { responsePromise, rejectFn } = this.trackInvokeMutationRequest<Data>(\n      requestId,\n      mapKey,\n      executeBody\n    );\n    responsePromise = responsePromise.finally(() => {\n      this.cleanupInvokeMutationRequest(requestId, mapKey);\n      if (!this.hasActiveSubscriptions && !this.hasActiveExecuteRequests) {\n        this.startIdleCloseTimeout();\n      }\n    });\n\n    // asynchronous, fire and forget\n    this.sendRequestMessage<Variables>(executeBody).catch(err => {\n      rejectFn(err);\n    });\n    return responsePromise;\n  }\n\n  /**\n   * @inheritdoc\n   * @remarks\n   * This method synchronously updates the request tracking data structures before sending any message\n   * or cancelling the closing of the stream. If any asynchronous functionality is added to this function,\n   * it MUST be done in a way that preserves the synchronous update of the tracking data structures\n   * before the method returns.\n   */\n  invokeSubscribe<Data, Variables>(\n    observer: SubscribeObserver<Data>,\n    queryName: string,\n    variables: Variables\n  ): void {\n    const mapKey = this.getMapKey(queryName, variables);\n    const existingSubscribe = this.activeInvokeSubscribeRequests.get(mapKey);\n\n    // if this query is pending cancellation, cancel the cancellation!\n    if (existingSubscribe) {\n      const requestId = existingSubscribe.requestId;\n      if (this.pendingCancellations.has(requestId)) {\n        this.pendingCancellations.delete(requestId);\n        this.subscribeObservers.set(requestId, observer);\n      }\n    } else {\n      const requestId = this.nextRequestId();\n      const activeRequestKey = { operationName: queryName, variables };\n      const subscribeBody: SubscribeStreamRequest<Variables> = {\n        requestId,\n        subscribe: activeRequestKey\n      };\n\n      this.trackInvokeSubscribeRequest<Data>(\n        requestId,\n        mapKey,\n        subscribeBody,\n        observer\n      );\n\n      // asynchronous, fire and forget\n      this.sendRequestMessage<Variables>(subscribeBody).catch(err => {\n        observer.onError(err instanceof Error ? err : new Error(String(err)));\n        this.cleanupInvokeSubscribeRequest(requestId, mapKey);\n        if (!this.hasActiveSubscriptions) {\n          this.startIdleCloseTimeout();\n        }\n      });\n    }\n    // if we are waiting to close the stream, cancel closing!\n    this.cancelClose();\n  }\n\n  /**\n   * @inheritdoc\n   * @remarks\n   * This method synchronously updates the request tracking data structures before sending any message.\n   * If any asynchronous functionality is added to this function, it MUST be done in a way that\n   * preserves the synchronous update of the tracking data structures before the method returns.\n   */\n  invokeUnsubscribe<Variables>(queryName: string, variables: Variables): void {\n    const mapKey = this.getMapKey(queryName, variables);\n    const subscribeRequest = this.activeInvokeSubscribeRequests.get(mapKey);\n    if (!subscribeRequest) {\n      return;\n    }\n    const requestId = subscribeRequest.requestId;\n\n    this.subscribeObservers.delete(requestId);\n    const resumePromise = this.resumeRequestPromises.get(requestId);\n    if (resumePromise) {\n      this.pendingCancellations.set(requestId, {\n        operationName: queryName,\n        variables\n      });\n      return;\n    }\n    this.cancelSubscription(requestId, mapKey);\n  }\n\n  /**\n   * Cancels a subscription, cleans up the request tracking data structures, and checks to see if we\n   * should close the stream due to inactivity.\n   */\n  private cancelSubscription(requestId: string, mapKey: string): void {\n    this.cleanupInvokeSubscribeRequest(requestId, mapKey);\n    const cancelBody: CancelStreamRequest = {\n      requestId,\n      cancel: {}\n    };\n\n    // asynchronous, fire and forget\n    this.sendRequestMessage(cancelBody).catch(err => {\n      logError(`Stream Transport failed to send unsubscribe message: ${err}`);\n    });\n\n    if (!this.hasActiveSubscriptions) {\n      this.startIdleCloseTimeout();\n    }\n  }\n\n  onAuthTokenChanged(newToken: string | null): void {\n    const oldAuthToken = this._authToken;\n    this._authToken = newToken;\n\n    const oldAuthUid = this.authUid;\n    const newAuthUid = this.authProvider?.getAuth()?.getUid();\n    this.authUid = newAuthUid;\n\n    // onAuthTokenChanged gets called by the auth provider once it initializes, so we must make sure\n    // we don't prematurely disconnect the stream if this is the initial call.\n    const isInitialAuth = oldAuthUid === undefined;\n    if (isInitialAuth) {\n      return;\n    }\n\n    if (\n      (oldAuthToken && newToken === null) || // user logged out\n      (!oldAuthUid && newAuthUid) || // user logged in\n      (oldAuthUid && newAuthUid !== oldAuthUid) // logged in user changed\n    ) {\n      void this.cleanupAndTerminate(\n        Code.UNAUTHORIZED,\n        'Stream disconnected due to auth change.'\n      );\n    }\n  }\n\n  /**\n   * Handle a response message from the server. Called by the connection-specific implementation after\n   * it's transformed a message from the server into a {@linkcode DataConnectResponse}.\n   * @param requestId the Request ID associated with this response.\n   * @param response the response from the server.\n   */\n  protected async handleResponse<Data>(\n    requestId: string,\n    response: DataConnectResponse<Data>\n  ): Promise<void> {\n    if (this.executeRequestPromises.has(requestId)) {\n      const { resolveFn, rejectFn } =\n        this.executeRequestPromises.get(requestId)!;\n      this.handleInvokeOperationResponse(resolveFn, rejectFn, response);\n    } else if (\n      this.subscribeObservers.has(requestId) ||\n      this.resumeRequestPromises.has(requestId)\n    ) {\n      const observer = this.subscribeObservers.get(requestId);\n      const resumePromise = this.resumeRequestPromises.get(requestId);\n\n      if (resumePromise) {\n        this.resumeRequestPromises.delete(requestId);\n        const { resolveFn, rejectFn } = resumePromise;\n        this.handleInvokeOperationResponse(resolveFn, rejectFn, response);\n      }\n\n      if (observer) {\n        try {\n          await observer.onData(response);\n        } catch (e) {\n          logError(`Error in observer callback: ${e}`);\n        }\n      }\n    } else {\n      logError(\n        `Stream response contained unrecognized requestId '${requestId}'`\n      );\n    }\n  }\n\n  /**\n   * Handles an invoke operation response, resolving or rejecting the promise returned to the user\n   * Does not handle any cleanup for requests - this should be handled by the caller or the promise's\n   * finally() block.\n   */\n  private handleInvokeOperationResponse<Data>(\n    resolveFn: (value: DataConnectResponse<Data>) => void,\n    rejectFn: (reason: unknown) => void,\n    response: DataConnectResponse<Data>\n  ): void {\n    if (response.errors && response.errors.length) {\n      const failureResponse: DataConnectOperationFailureResponse = {\n        errors: response.errors as [],\n        data: response.data as Record<string, unknown>\n      };\n      const stringified = JSON.stringify(response.errors);\n      rejectFn(\n        new DataConnectOperationError(\n          'DataConnect error while performing request: ' + stringified,\n          failureResponse\n        )\n      );\n    } else {\n      resolveFn(response);\n    }\n  }\n}\n","/**\n * @license\n * Copyright 2026 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Code, DataConnectError } from '../../core/error';\nimport { logError } from '../../logger';\nimport { websocketUrlBuilder } from '../../util/url';\nimport { DataConnectResponse } from '../transport';\n\nimport { AbstractDataConnectStreamTransport } from './streamTransport';\nimport { DataConnectStreamRequest, DataConnectStreamResponse } from './wire';\n\n/** The WebSocket implementation to be used by the {@link WebSocketTransport}. */\nlet connectWebSocket: typeof WebSocket | null = globalThis.WebSocket;\n\n/**\n * This function is ONLY used for testing and for ensuring compatability in environments which may\n * be using a poyfill and/or bundlers. It should not be called by users of the Firebase JS SDK.\n * @internal\n */\nexport function initializeWebSocket(webSocketImpl: typeof WebSocket): void {\n  connectWebSocket = webSocketImpl;\n}\n\n/**\n * The code used to close the WebSocket connection.\n * This is a protocol-level code, and is not the same as the {@link Code | DataConnect error code}.\n * @internal\n */\nexport const WEBSOCKET_CLOSE_CODE = 1000;\n\n/**\n * An {@link AbstractDataConnectStreamTransport | Stream Transport} implementation that uses {@link WebSocket | WebSockets} to stream requests and responses.\n * This class handles the lifecycle of the WebSocket connection, including automatic\n * reconnection and request correlation.\n * @internal\n */\nexport class WebSocketTransport extends AbstractDataConnectStreamTransport {\n  get endpointUrl(): string {\n    return websocketUrlBuilder(\n      {\n        connector: this._connectorName,\n        location: this._location,\n        projectId: this._project,\n        service: this._serviceName\n      },\n      {\n        host: this._host,\n        sslEnabled: this._secure,\n        port: this._port\n      }\n    );\n  }\n\n  /** Decodes binary WebSocket responses to strings */\n  private decoder: TextDecoder | undefined = undefined;\n\n  /**\n   * Decodes a WebSocket response from a Uint8Array to a JSON object.\n   * Emulator does not send messages as Uint8Arrays, but prod does.\n   */\n  private decodeBinaryResponse(data: ArrayBuffer): string {\n    if (!this.decoder) {\n      this.decoder = new TextDecoder('utf-8');\n    }\n    return this.decoder.decode(data);\n  }\n\n  /** The current connection to the server. Undefined if disconnected. */\n  private connection: WebSocket | undefined = undefined;\n\n  get streamIsReady(): boolean {\n    return this.connection?.readyState === WebSocket.OPEN;\n  }\n\n  /**\n   * Current connection attempt. If null, we are not currently attemping to connect (not connected,\n   * or already connected). Will be resolved or rejected when the connection is opened or fails to open.\n   */\n  private connectionAttempt: Promise<void> | null = null;\n\n  protected ensureConnection(): Promise<void> {\n    try {\n      if (this.streamIsReady) {\n        return Promise.resolve();\n      }\n      if (this.connectionAttempt) {\n        return this.connectionAttempt;\n      }\n      this.connectionAttempt = new Promise<void>((resolve, reject) => {\n        if (!connectWebSocket) {\n          throw new DataConnectError(\n            Code.OTHER,\n            'No WebSocket Implementation detected!'\n          );\n        }\n        const ws = new connectWebSocket(this.endpointUrl);\n        this.connection = ws;\n        this.connection!.binaryType = 'arraybuffer';\n\n        ws.onopen = () => {\n          this.isUnableToConnect = false;\n          this.onConnectionReady();\n          resolve();\n        };\n\n        ws.onerror = event => {\n          this.connectionAttempt = null;\n          this.isUnableToConnect = true;\n          const error = new DataConnectError(\n            Code.OTHER,\n            `Error using WebSocket connection, closing WebSocket`\n          );\n          this.handleError(error);\n          reject(error);\n        };\n\n        ws.onmessage = ev =>\n          this.handleWebSocketMessage(ev).catch(async reason => {\n            this.handleError(reason);\n          });\n\n        ws.onclose = ev => this.handleWebsocketDisconnect(ev);\n      });\n\n      return this.connectionAttempt;\n    } catch (error) {\n      this.handleError(error);\n      throw error;\n    }\n  }\n\n  protected openConnection(): Promise<void> {\n    return this.ensureConnection().catch(err => {\n      throw new DataConnectError(\n        Code.OTHER,\n        `Failed to open connection: ${err}`\n      );\n    });\n  }\n\n  protected closeConnection(code?: number, reason?: string): Promise<void> {\n    if (!this.connection) {\n      this.connectionAttempt = null;\n      return Promise.resolve();\n    }\n    let error;\n    try {\n      if (reason) {\n        // reason string can be max 123 bytes (not characters, bytes)\n        // https://developer.mozilla.org/en-US/docs/Web/API/WebSocketStream/close#parameters\n        const MAX_BYTES = 123;\n        const encoder = new TextEncoder();\n        const bytes = encoder.encode(reason);\n        if (bytes.length <= MAX_BYTES) {\n          this.connection.close(code, reason);\n        } else {\n          const buf = new Uint8Array(MAX_BYTES);\n          const { read } = encoder.encodeInto(reason, buf);\n          const truncatedReason = reason.substring(0, read);\n          this.connection.close(code, truncatedReason);\n        }\n      } else {\n        this.connection.close(code);\n      }\n    } catch (e) {\n      error = e;\n    } finally {\n      this.connection = undefined;\n      this.connectionAttempt = null;\n    }\n    if (error) {\n      return Promise.reject(error);\n    }\n    return Promise.resolve();\n  }\n\n  /**\n   * Handle a disconnection from the server. Initiates graceful clean up and reconnection attempts.\n   * @param ev the {@link CloseEvent} that closed the WebSocket.\n   */\n  private handleWebsocketDisconnect(ev: CloseEvent): void {\n    this.connection = undefined;\n    this.connectionAttempt = null;\n    this.onStreamClose(ev.code, ev.reason);\n  }\n\n  /**\n   * Handle an error that occurred on the WebSocket. Close the connection and reject all active requests.\n   */\n  private handleError(error?: unknown): void {\n    logError(`DataConnect WebSocket error, closing stream: ${error}`);\n    let reason = error ? String(error) : 'Unknown Error';\n    if (error instanceof DataConnectError) {\n      reason = error.message;\n    }\n    void this.closeConnection(WEBSOCKET_CLOSE_CODE, reason);\n  }\n\n  protected sendMessage<Variables>(\n    requestBody: DataConnectStreamRequest<Variables>\n  ): Promise<void> {\n    return this.ensureConnection().then(() => {\n      try {\n        this.connection!.send(JSON.stringify(requestBody));\n        return Promise.resolve();\n      } catch (err) {\n        this.handleError(err);\n        throw new DataConnectError(\n          Code.OTHER,\n          `Failed to send message: ${String(err)}`\n        );\n      }\n    });\n  }\n\n  /**\n   * Handles incoming WebSocket messages.\n   * @param ev The {@link MessageEvent} from the WebSocket.\n   */\n  private async handleWebSocketMessage(ev: MessageEvent): Promise<void> {\n    const result: DataConnectStreamResponse<unknown> = this.parseWebSocketData(\n      ev.data\n    );\n    const requestId = result.requestId;\n\n    const response: DataConnectResponse<unknown> = {\n      data: result.data,\n      errors: result.errors,\n      extensions: result.extensions || { dataConnect: [] }\n    };\n\n    await this.handleResponse(requestId, response);\n  }\n\n  /**\n   * Parse a response from the server. Assert that it has a {@link DataConnectStreamResponse.requestId | requestId}.\n   * @param data the message from the server to be parsed\n   * @returns the parsed message as a {@link DataConnectStreamResponse}\n   * @throws {DataConnectError} if parsing fails or message is malformed.\n   */\n  private parseWebSocketData<Data>(\n    // eslint-disable-next-line @typescript-eslint/no-explicit-any\n    data: any\n  ): DataConnectStreamResponse<Data> {\n    const dataIsString = typeof data === 'string';\n    /** raw websocket message */\n    let webSocketMessage;\n    /** object containing data, errors, and extensions */\n    let result;\n    try {\n      if (dataIsString) {\n        webSocketMessage = JSON.parse(data);\n      } else {\n        webSocketMessage = JSON.parse(this.decodeBinaryResponse(data));\n      }\n    } catch (err) {\n      throw new DataConnectError(\n        Code.OTHER,\n        `Could not parse WebSocket message: ${\n          err instanceof Error ? err.message : String(err)\n        }`\n      );\n    }\n    if (typeof webSocketMessage !== 'object' || webSocketMessage === null) {\n      throw new DataConnectError(\n        Code.OTHER,\n        'WebSocket message is not an object'\n      );\n    }\n    if (dataIsString) {\n      if (!('result' in webSocketMessage)) {\n        throw new DataConnectError(\n          Code.OTHER,\n          'WebSocket message from emulator did not include result'\n        );\n      }\n      if (\n        typeof webSocketMessage.result !== 'object' ||\n        webSocketMessage.result === null\n      ) {\n        throw new DataConnectError(\n          Code.OTHER,\n          'WebSocket message result is not an object'\n        );\n      }\n      result = webSocketMessage.result;\n    } else {\n      result = webSocketMessage;\n    }\n    if (!('requestId' in result)) {\n      throw new DataConnectError(\n        Code.OTHER,\n        'WebSocket message did not include requestId'\n      );\n    }\n    return result;\n  }\n}\n","/**\n * @license\n * Copyright 2026 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { DataConnectOptions, TransportOptions } from '../api/DataConnect';\nimport { AppCheckTokenProvider } from '../core/AppCheckTokenProvider';\nimport { Code, DataConnectError } from '../core/error';\nimport { AuthTokenProvider } from '../core/FirebaseAuthProvider';\n\nimport { RESTTransport } from './rest';\nimport { AbstractDataConnectStreamTransport } from './stream/streamTransport';\nimport { WebSocketTransport } from './stream/websocket';\nimport {\n  CallerSdkType,\n  DataConnectResponse,\n  DataConnectResponseWithMaxAge,\n  DataConnectTransportInterface,\n  SubscribeObserver\n} from './transport';\n\n/**\n * Entry point for the transport layer. Manages routing between transport implementations.\n * @internal\n */\nexport class DataConnectTransportManager\n  implements DataConnectTransportInterface\n{\n  private restTransport: RESTTransport;\n  private streamTransport?: AbstractDataConnectStreamTransport;\n  private isUsingEmulator = false;\n\n  constructor(\n    private options: DataConnectOptions,\n    private apiKey?: string,\n    private appId?: string | null,\n    private authProvider?: AuthTokenProvider,\n    private appCheckProvider?: AppCheckTokenProvider,\n    private transportOptions?: TransportOptions,\n    private _isUsingGen = false,\n    private _callerSdkType?: CallerSdkType\n  ) {\n    this.restTransport = new RESTTransport(\n      options,\n      apiKey,\n      appId,\n      authProvider,\n      appCheckProvider,\n      transportOptions,\n      _isUsingGen,\n      _callerSdkType\n    );\n  }\n\n  /**\n   * Initializes the stream transport if it hasn't been already.\n   */\n  private initStreamTransport(): AbstractDataConnectStreamTransport {\n    if (!this.streamTransport) {\n      this.streamTransport = new WebSocketTransport(\n        this.options,\n        this.apiKey,\n        this.appId,\n        this.authProvider,\n        this.appCheckProvider,\n        this.transportOptions,\n        this._isUsingGen,\n        this._callerSdkType\n      );\n      if (this.isUsingEmulator && this.transportOptions) {\n        this.streamTransport.useEmulator(\n          this.transportOptions.host!,\n          this.transportOptions.port,\n          this.transportOptions.sslEnabled\n        );\n      }\n      this.streamTransport.onCloseCallback = () => {\n        this.streamTransport = undefined;\n      };\n    }\n    return this.streamTransport;\n  }\n\n  /**\n   * Returns true if the stream is in a healthy, ready connection state and has active subscriptions.\n   */\n  private executeShouldUseStream(): boolean {\n    return (\n      !!this.streamTransport &&\n      !this.streamTransport.isPendingClose &&\n      this.streamTransport.streamIsReady &&\n      this.streamTransport.hasActiveSubscriptions &&\n      !this.streamTransport.isUnableToConnect\n    );\n  }\n\n  /**\n   * Prefer to use Streaming Transport connection when one is available.\n   * @inheritdoc\n   */\n  invokeQuery<Data, Variables>(\n    queryName: string,\n    body?: Variables\n  ): Promise<DataConnectResponseWithMaxAge<Data>> {\n    if (this.executeShouldUseStream()) {\n      return this.streamTransport!.invokeQuery<Data, Variables>(\n        queryName,\n        body\n      ).catch(err => {\n        if (this.executeShouldUseStream()) {\n          throw err;\n        }\n        return this.restTransport.invokeQuery<Data, Variables>(queryName, body);\n      });\n    }\n    return this.restTransport.invokeQuery(queryName, body);\n  }\n\n  /**\n   * Prefer to use Streaming Transport connection when one is available.\n   * @inheritdoc\n   */\n  invokeMutation<Data, Variables>(\n    queryName: string,\n    body?: Variables\n  ): Promise<DataConnectResponse<Data>> {\n    if (this.executeShouldUseStream()) {\n      return this.streamTransport!.invokeMutation<Data, Variables>(\n        queryName,\n        body\n      ).catch(err => {\n        if (this.executeShouldUseStream()) {\n          throw err;\n        }\n        return this.restTransport.invokeMutation<Data, Variables>(\n          queryName,\n          body\n        );\n      });\n    }\n    return this.restTransport.invokeMutation(queryName, body);\n  }\n\n  invokeSubscribe<Data, Variables>(\n    observer: SubscribeObserver<Data>,\n    queryName: string,\n    body?: Variables\n  ): void {\n    const streamTransport = this.initStreamTransport();\n    if (streamTransport.isUnableToConnect) {\n      throw new DataConnectError(\n        Code.OTHER,\n        'Unable to connect streaming connection to server. Subscriptions are unavailable.'\n      );\n    }\n    streamTransport.invokeSubscribe(observer, queryName, body);\n  }\n\n  invokeUnsubscribe<Variables>(queryName: string, body?: Variables): void {\n    if (this.streamTransport) {\n      this.streamTransport.invokeUnsubscribe(queryName, body);\n    }\n  }\n\n  useEmulator(host: string, port?: number, sslEnabled?: boolean): void {\n    this.isUsingEmulator = true;\n    this.transportOptions = { host, port, sslEnabled };\n    this.restTransport.useEmulator(host, port, sslEnabled);\n    if (this.streamTransport) {\n      this.streamTransport.useEmulator(host, port, sslEnabled);\n    }\n  }\n\n  onAuthTokenChanged(token: string | null): void {\n    this.restTransport.onAuthTokenChanged(token);\n    if (this.streamTransport) {\n      this.streamTransport.onAuthTokenChanged(token);\n    }\n  }\n\n  _setCallerSdkType(callerSdkType: CallerSdkType): void {\n    this._callerSdkType = callerSdkType;\n    this.restTransport._setCallerSdkType(callerSdkType);\n    if (this.streamTransport) {\n      this.streamTransport._setCallerSdkType(callerSdkType);\n    }\n  }\n}\n","/**\n * @license\n * Copyright 2024 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { DataConnectTransportInterface } from '../network';\n\nimport { DataConnect } from './DataConnect';\nimport {\n  DataConnectResult,\n  MUTATION_STR,\n  OperationRef,\n  SOURCE_SERVER\n} from './Reference';\n\nexport interface MutationRef<Data, Variables>\n  extends OperationRef<Data, Variables> {\n  refType: typeof MUTATION_STR;\n}\n\n/**\n * Creates a `MutationRef`\n * @param dcInstance Data Connect instance\n * @param mutationName name of mutation\n */\nexport function mutationRef<Data>(\n  dcInstance: DataConnect,\n  mutationName: string\n): MutationRef<Data, undefined>;\n/**\n *\n * @param dcInstance Data Connect instance\n * @param mutationName name of mutation\n * @param variables variables to send with mutation\n */\nexport function mutationRef<Data, Variables>(\n  dcInstance: DataConnect,\n  mutationName: string,\n  variables: Variables\n): MutationRef<Data, Variables>;\n/**\n *\n * @param dcInstance Data Connect instance\n * @param mutationName name of mutation\n * @param variables variables to send with mutation\n * @returns `MutationRef`\n */\nexport function mutationRef<Data, Variables>(\n  dcInstance: DataConnect,\n  mutationName: string,\n  variables?: Variables\n): MutationRef<Data, Variables> {\n  dcInstance.setInitialized();\n  const ref: MutationRef<Data, Variables> = {\n    dataConnect: dcInstance,\n    name: mutationName,\n    refType: MUTATION_STR,\n    variables: variables as Variables\n  };\n  return ref;\n}\n\n/**\n * @internal\n */\nexport class MutationManager {\n  private _inflight: Array<Promise<unknown>> = [];\n  constructor(private _transport: DataConnectTransportInterface) {}\n  executeMutation<Data, Variables>(\n    mutationRef: MutationRef<Data, Variables>\n  ): MutationPromise<Data, Variables> {\n    const result = this._transport.invokeMutation<Data, Variables>(\n      mutationRef.name,\n      mutationRef.variables\n    );\n    const withRefPromise = result.then(res => {\n      const obj: MutationResult<Data, Variables> = {\n        ...res, // Double check that the result is result.data, not just result\n        source: SOURCE_SERVER,\n        ref: mutationRef,\n        fetchTime: Date.now().toLocaleString()\n      };\n      return obj;\n    });\n    this._inflight.push(result);\n    const removePromise = (): Array<Promise<unknown>> =>\n      (this._inflight = this._inflight.filter(promise => promise !== result));\n    result.then(removePromise, removePromise);\n    return withRefPromise;\n  }\n}\n\n/**\n * Mutation Result from `executeMutation`\n */\nexport interface MutationResult<Data, Variables>\n  extends DataConnectResult<Data, Variables> {\n  ref: MutationRef<Data, Variables>;\n}\n/**\n * Mutation return value from `executeMutation`\n */\nexport interface MutationPromise<Data, Variables>\n  extends Promise<MutationResult<Data, Variables>> {\n  // reserved for special actions like cancellation\n}\n\n/**\n * Execute Mutation\n * @param mutationRef mutation to execute\n * @returns `MutationRef`\n */\nexport function executeMutation<Data, Variables>(\n  mutationRef: MutationRef<Data, Variables>\n): MutationPromise<Data, Variables> {\n  return mutationRef.dataConnect._mutationManager.executeMutation(mutationRef);\n}\n","/**\n * @license\n * Copyright 2024 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n  FirebaseApp,\n  _getProvider,\n  _removeServiceInstance,\n  getApp\n} from '@firebase/app';\nimport { AppCheckInternalComponentName } from '@firebase/app-check-interop-types';\nimport { FirebaseAuthInternalName } from '@firebase/auth-interop-types';\nimport { Provider } from '@firebase/component';\nimport { isCloudWorkstation, pingServer } from '@firebase/util';\n\nimport { DataConnectCache, MemoryStub } from '../cache/Cache';\nimport { InternalCacheProvider } from '../cache/CacheProvider';\nimport { AppCheckTokenProvider } from '../core/AppCheckTokenProvider';\nimport { Code, DataConnectError } from '../core/error';\nimport {\n  AuthTokenProvider,\n  FirebaseAuthProvider\n} from '../core/FirebaseAuthProvider';\nimport { QueryManager } from '../core/query/QueryManager';\nimport { logDebug, logError } from '../logger';\nimport {\n  DataConnectTransportInterface,\n  TransportClass,\n  CallerSdkType,\n  CallerSdkTypeEnum\n} from '../network';\nimport { DataConnectTransportManager } from '../network/manager';\nimport { PROD_HOST } from '../util/url';\n\nimport { MutationManager } from './Mutation';\n\n/**\n * Connector Config for calling Data Connect backend.\n */\nexport interface ConnectorConfig {\n  location: string;\n  connector: string;\n  service: string;\n}\n\n/**\n * Options to connect to emulator\n */\nexport interface TransportOptions {\n  host: string;\n  sslEnabled?: boolean;\n  port?: number;\n}\n\nconst FIREBASE_DATA_CONNECT_EMULATOR_HOST_VAR =\n  'FIREBASE_DATA_CONNECT_EMULATOR_HOST';\n\n/**\n *\n * @param fullHost\n * @returns TransportOptions\n * @internal\n */\nexport function parseOptions(fullHost: string): TransportOptions {\n  const [protocol, hostName] = fullHost.split('://');\n  const isSecure = protocol === 'https';\n  const [host, portAsString] = hostName.split(':');\n  const port = Number(portAsString);\n  return { host, port, sslEnabled: isSecure };\n}\n/**\n * DataConnectOptions including project id\n */\nexport interface DataConnectOptions extends ConnectorConfig {\n  projectId: string;\n}\n\n/**\n * Class representing Firebase Data Connect\n */\nexport class DataConnect {\n  _queryManager!: QueryManager;\n  _mutationManager!: MutationManager;\n  isEmulator = false;\n  _initialized = false;\n  private _transport!: DataConnectTransportInterface;\n  private _transportClass: TransportClass | undefined;\n  private _transportOptions?: TransportOptions;\n  private _authTokenProvider?: AuthTokenProvider;\n  _isUsingGeneratedSdk: boolean = false;\n  _callerSdkType: CallerSdkType = CallerSdkTypeEnum.Base;\n  private _appCheckTokenProvider?: AppCheckTokenProvider;\n  private _cacheSettings?: CacheSettings;\n  /**\n   * @internal\n   */\n  private cache?: DataConnectCache;\n  // @internal\n  constructor(\n    public readonly app: FirebaseApp,\n    // TODO(mtewani): Replace with _dataConnectOptions in the future\n    private readonly dataConnectOptions: DataConnectOptions,\n    private readonly _authProvider: Provider<FirebaseAuthInternalName>,\n    private readonly _appCheckProvider: Provider<AppCheckInternalComponentName>\n  ) {\n    if (typeof process !== 'undefined' && process.env) {\n      const host = process.env[FIREBASE_DATA_CONNECT_EMULATOR_HOST_VAR];\n      if (host) {\n        logDebug('Found custom host. Using emulator');\n        this.isEmulator = true;\n        this._transportOptions = parseOptions(host);\n      }\n    }\n  }\n  /**\n   * @internal\n   */\n  getCache(): DataConnectCache | undefined {\n    return this.cache;\n  }\n  // @internal\n  _useGeneratedSdk(): void {\n    if (!this._isUsingGeneratedSdk) {\n      this._isUsingGeneratedSdk = true;\n    }\n  }\n  _setCallerSdkType(callerSdkType: CallerSdkType): void {\n    this._callerSdkType = callerSdkType;\n    if (this._initialized) {\n      this._transport._setCallerSdkType(callerSdkType);\n    }\n  }\n  _delete(): Promise<void> {\n    _removeServiceInstance(\n      this.app,\n      'data-connect',\n      JSON.stringify(this.getSettings())\n    );\n    return Promise.resolve();\n  }\n\n  // @internal\n  getSettings(): ConnectorConfig {\n    const copy = JSON.parse(JSON.stringify(this.dataConnectOptions));\n    delete copy.projectId;\n    return copy;\n  }\n\n  /**\n   * @internal\n   */\n  setCacheSettings(cacheSettings: CacheSettings): void {\n    this._cacheSettings = cacheSettings;\n  }\n\n  // @internal\n  setInitialized(): void {\n    if (this._initialized) {\n      return;\n    }\n    if (this._transportClass === undefined) {\n      logDebug(\n        'transportClass not provided. Defaulting to DataConnectTransportManager.'\n      );\n      this._transportClass = DataConnectTransportManager;\n    }\n\n    this._authTokenProvider = new FirebaseAuthProvider(\n      this.app.name,\n      this.app.options,\n      this._authProvider\n    );\n    const connectorConfig: ConnectorConfig = {\n      connector: this.dataConnectOptions.connector,\n      service: this.dataConnectOptions.service,\n      location: this.dataConnectOptions.location\n    };\n    if (this._cacheSettings) {\n      this.cache = new DataConnectCache(\n        this._authTokenProvider,\n        this.app.options.projectId!,\n        connectorConfig,\n        this._transportOptions?.host || PROD_HOST,\n        this._cacheSettings\n      );\n    }\n\n    if (this._appCheckProvider) {\n      this._appCheckTokenProvider = new AppCheckTokenProvider(\n        this.app,\n        this._appCheckProvider\n      );\n    }\n\n    this._transport = new this._transportClass(\n      this.dataConnectOptions,\n      this.app.options.apiKey,\n      this.app.options.appId,\n      this._authTokenProvider,\n      this._appCheckTokenProvider,\n      undefined,\n      this._isUsingGeneratedSdk,\n      this._callerSdkType\n    );\n    if (this._transportOptions) {\n      this._transport.useEmulator(\n        this._transportOptions.host,\n        this._transportOptions.port,\n        this._transportOptions.sslEnabled\n      );\n    }\n\n    this._queryManager = new QueryManager(this._transport, this, this.cache);\n    this._mutationManager = new MutationManager(this._transport);\n    this._initialized = true;\n  }\n\n  // @internal\n  enableEmulator(transportOptions: TransportOptions): void {\n    if (\n      this._transportOptions &&\n      this._initialized &&\n      !areTransportOptionsEqual(this._transportOptions, transportOptions)\n    ) {\n      logError('enableEmulator called after initialization');\n      throw new DataConnectError(\n        Code.ALREADY_INITIALIZED,\n        'DataConnect instance already initialized!'\n      );\n    }\n    this._transportOptions = transportOptions;\n    this.isEmulator = true;\n  }\n}\n\n/**\n * @internal\n * @param transportOptions1\n * @param transportOptions2\n * @returns\n */\nexport function areTransportOptionsEqual(\n  transportOptions1: TransportOptions,\n  transportOptions2: TransportOptions\n): boolean {\n  return (\n    transportOptions1.host === transportOptions2.host &&\n    transportOptions1.port === transportOptions2.port &&\n    transportOptions1.sslEnabled === transportOptions2.sslEnabled\n  );\n}\n\n/**\n * Connect to the DataConnect Emulator\n * @param dc Data Connect instance\n * @param host host of emulator server\n * @param port port of emulator server\n * @param sslEnabled use https\n */\nexport function connectDataConnectEmulator(\n  dc: DataConnect,\n  host: string,\n  port?: number,\n  sslEnabled = false\n): void {\n  // Workaround to get cookies in Firebase Studio\n  if (isCloudWorkstation(host)) {\n    void pingServer(`https://${host}${port ? `:${port}` : ''}`);\n  }\n  dc.enableEmulator({ host, port, sslEnabled });\n}\n\nexport interface DataConnectSettings {\n  cacheSettings?: CacheSettings;\n}\n\n/**\n * Initialize DataConnect instance\n * @param options ConnectorConfig\n */\nexport function getDataConnect(\n  options: ConnectorConfig,\n  settings?: DataConnectSettings\n): DataConnect;\nexport function getDataConnect(options: ConnectorConfig): DataConnect;\n/**\n * Initialize DataConnect instance\n * @param app FirebaseApp to initialize to.\n * @param connectorConfig ConnectorConfig\n */\nexport function getDataConnect(\n  app: FirebaseApp,\n  connectorConfig: ConnectorConfig\n): DataConnect;\n\n/**\n * Initialize DataConnect instance\n * @param app FirebaseApp to initialize to.\n * @param connectorConfig ConnectorConfig\n */\nexport function getDataConnect(\n  app: FirebaseApp,\n  connectorConfig: ConnectorConfig,\n  settings: DataConnectSettings\n): DataConnect;\n\nexport function getDataConnect(\n  appOrConnectorConfig: FirebaseApp | ConnectorConfig,\n  settingsOrConnectorConfig?: ConnectorConfig | DataConnectSettings,\n  settings?: DataConnectSettings\n): DataConnect {\n  let app: FirebaseApp;\n  let connectorConfig: ConnectorConfig;\n  let realSettings: DataConnectSettings;\n  if ('location' in appOrConnectorConfig) {\n    connectorConfig = appOrConnectorConfig;\n    app = getApp();\n    realSettings = settingsOrConnectorConfig as DataConnectSettings;\n  } else {\n    app = appOrConnectorConfig;\n    connectorConfig = settingsOrConnectorConfig as ConnectorConfig;\n    realSettings = settings as DataConnectSettings;\n  }\n\n  if (!app || Object.keys(app).length === 0) {\n    app = getApp();\n  }\n\n  // Options to store in Firebase Component Provider.\n  const serializedOptions = {\n    ...connectorConfig,\n    projectId: app.options.projectId\n  };\n\n  // We should sort the keys before initialization.\n  const sortedSerialized = Object.fromEntries(\n    Object.entries(serializedOptions).sort()\n  );\n\n  const provider = _getProvider(app, 'data-connect');\n  const identifier = JSON.stringify(sortedSerialized);\n  if (provider.isInitialized(identifier)) {\n    const dcInstance = provider.getImmediate({ identifier });\n    const options = provider.getOptions(identifier);\n    const optionsValid = Object.keys(options).length > 0;\n    if (optionsValid) {\n      logDebug('Re-using cached instance');\n      return dcInstance;\n    }\n  }\n  validateDCOptions(connectorConfig);\n\n  logDebug('Creating new DataConnect instance');\n  // Initialize with options.\n  const dataConnect = provider.initialize({\n    instanceIdentifier: identifier,\n    options: Object.fromEntries(\n      Object.entries({\n        ...sortedSerialized\n      }).sort()\n    )\n  });\n  if (realSettings?.cacheSettings) {\n    dataConnect.setCacheSettings(realSettings.cacheSettings);\n  }\n  return dataConnect;\n}\n\n/**\n *\n * @param dcOptions\n * @returns {void}\n * @internal\n */\nexport function validateDCOptions(dcOptions: ConnectorConfig): boolean {\n  const fields = ['connector', 'location', 'service'];\n  if (!dcOptions) {\n    throw new DataConnectError(Code.INVALID_ARGUMENT, 'DC Option Required');\n  }\n  fields.forEach(field => {\n    if (\n      dcOptions[field as keyof ConnectorConfig] === null ||\n      dcOptions[field as keyof ConnectorConfig] === undefined\n    ) {\n      throw new DataConnectError(Code.INVALID_ARGUMENT, `${field} Required`);\n    }\n  });\n  return true;\n}\n\n/**\n * Delete DataConnect instance\n * @param dataConnect DataConnect instance\n * @returns\n */\nexport function terminate(dataConnect: DataConnect): Promise<void> {\n  return dataConnect._delete();\n  // TODO(mtewani): Stop pending tasks\n}\nexport const StorageType = {\n  MEMORY: 'MEMORY'\n} as const;\n\nexport type StorageType = (typeof StorageType)[keyof typeof StorageType];\n\nexport interface CacheSettings {\n  cacheProvider: CacheProvider<StorageType>;\n  maxAgeSeconds?: number;\n}\nexport interface CacheProvider<T extends StorageType> {\n  type: T;\n  /**\n   * @internal\n   */\n  initialize(cacheId: string): InternalCacheProvider;\n}\n\nexport function makeMemoryCacheProvider(): CacheProvider<'MEMORY'> {\n  return new MemoryStub();\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport const QueryFetchPolicy = {\n  PREFER_CACHE: 'PREFER_CACHE',\n  CACHE_ONLY: 'CACHE_ONLY',\n  SERVER_ONLY: 'SERVER_ONLY'\n} as const;\n\n/*\n * Represents policy for how executeQuery fetches data\n */\nexport type QueryFetchPolicy =\n  (typeof QueryFetchPolicy)[keyof typeof QueryFetchPolicy];\n\n/**\n * Options for executing a query.\n */\nexport interface ExecuteQueryOptions {\n  fetchPolicy: QueryFetchPolicy;\n}\n","/**\n * @license\n * Copyright 2024 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Code, DataConnectError } from '../core/error';\nimport {\n  ExecuteQueryOptions,\n  QueryFetchPolicy\n} from '../core/query/queryOptions';\nimport { DataConnectExtensionWithMaxAge } from '../network';\n\nimport { DataConnect, getDataConnect } from './DataConnect';\nimport {\n  OperationRef,\n  QUERY_STR,\n  DataConnectResult,\n  SerializedRef\n} from './Reference';\n\n/**\n * QueryRef object\n */\nexport interface QueryRef<Data, Variables>\n  extends OperationRef<Data, Variables> {\n  refType: typeof QUERY_STR;\n}\n\n/** @internal */\nexport type InternalQueryResult<Data, Variables> = QueryResult<\n  Data,\n  Variables\n> &\n  Omit<DataConnectResult<Data, Variables>, 'extensions'> & {\n    extensions?: {\n      dataConnect?: DataConnectExtensionWithMaxAge[];\n    };\n  };\n\n/**\n * Result of `executeQuery`\n */\nexport interface QueryResult<Data, Variables>\n  extends DataConnectResult<Data, Variables> {\n  ref: QueryRef<Data, Variables>;\n  toJSON: () => SerializedRef<Data, Variables>;\n}\n/**\n * Promise returned from `executeQuery`\n */\nexport interface QueryPromise<Data, Variables>\n  extends Promise<QueryResult<Data, Variables>> {\n  // reserved for special actions like cancellation\n}\n\n/**\n * Execute Query\n * @param queryRef query to execute.\n * @returns `QueryPromise`\n */\nexport function executeQuery<Data, Variables>(\n  queryRef: QueryRef<Data, Variables>,\n  options?: ExecuteQueryOptions\n): QueryPromise<Data, Variables> {\n  if (queryRef.refType !== QUERY_STR) {\n    return Promise.reject(\n      new DataConnectError(\n        Code.INVALID_ARGUMENT,\n        `ExecuteQuery can only execute query operations`\n      )\n    );\n  }\n  const queryManager = queryRef.dataConnect._queryManager;\n  const fetchPolicy = options?.fetchPolicy ?? QueryFetchPolicy.PREFER_CACHE;\n  switch (fetchPolicy) {\n    case QueryFetchPolicy.SERVER_ONLY:\n      return queryManager.fetchServerResults(queryRef);\n    case QueryFetchPolicy.CACHE_ONLY:\n      return queryManager.fetchCacheResults(queryRef, true);\n    case QueryFetchPolicy.PREFER_CACHE:\n      return queryManager.preferCacheResults(queryRef, false);\n    default:\n      throw new DataConnectError(\n        Code.INVALID_ARGUMENT,\n        `Invalid fetch policy: ${fetchPolicy}`\n      );\n  }\n}\n\n/**\n * Execute Query\n * @param dcInstance Data Connect instance to use.\n * @param queryName Query to execute\n * @returns `QueryRef`\n */\nexport function queryRef<Data>(\n  dcInstance: DataConnect,\n  queryName: string\n): QueryRef<Data, undefined>;\n/**\n * Execute Query\n * @param dcInstance Data Connect instance to use.\n * @param queryName Query to execute\n * @param variables Variables to execute with\n * @returns `QueryRef`\n */\nexport function queryRef<Data, Variables>(\n  dcInstance: DataConnect,\n  queryName: string,\n  variables: Variables\n): QueryRef<Data, Variables>;\n/**\n * Execute Query\n * @param dcInstance Data Connect instance to use.\n * @param queryName Query to execute\n * @param variables Variables to execute with\n * @param initialCache initial cache to use for client hydration\n * @returns `QueryRef`\n */\nexport function queryRef<Data, Variables>(\n  dcInstance: DataConnect,\n  queryName: string,\n  variables?: Variables,\n  initialCache?: QueryResult<Data, Variables>\n): QueryRef<Data, Variables> {\n  dcInstance.setInitialized();\n  if (initialCache !== undefined) {\n    dcInstance._queryManager.updateSSR(initialCache);\n  }\n  return {\n    dataConnect: dcInstance,\n    refType: QUERY_STR,\n    name: queryName,\n    variables: variables as Variables\n  };\n}\n/**\n * Converts serialized ref to query ref\n * @param serializedRef ref to convert to `QueryRef`\n * @returns `QueryRef`\n */\nexport function toQueryRef<Data, Variables>(\n  serializedRef: SerializedRef<Data, Variables>\n): QueryRef<Data, Variables> {\n  const {\n    refInfo: { name, variables, connectorConfig }\n  } = serializedRef;\n  return queryRef(getDataConnect(connectorConfig), name, variables);\n}\n","/**\n * @license\n * Copyright 2024 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { ExecuteQueryOptions } from '../api';\nimport {\n  ConnectorConfig,\n  DataConnect,\n  getDataConnect\n} from '../api/DataConnect';\nimport { Code, DataConnectError } from '../core/error';\n\ninterface ParsedArgs<Variables> {\n  dc: DataConnect;\n  vars: Variables;\n  options?: ExecuteQueryOptions;\n}\n\n/**\n * The generated SDK will allow the user to pass in either the variables or the data connect instance\n * with the variables. This function validates the variables and returns back the DataConnect instance\n * and variables based on the arguments passed in.\n *\n * Generated SDKs generated from versions 3.2.0 and lower of the Data Connect emulator binary are\n * NOT concerned with options, and will use this function to validate arguments.\n *\n * @param connectorConfig\n * @param dcOrVars\n * @param vars\n * @param variablesRequired\n * @returns {DataConnect} and {Variables} instance\n * @internal\n */\nexport function validateArgs<Variables extends object>(\n  connectorConfig: ConnectorConfig,\n  dcOrVars?: DataConnect | Variables,\n  vars?: Variables,\n  variablesRequired?: boolean\n): ParsedArgs<Variables> {\n  let dcInstance: DataConnect;\n  let realVars: Variables;\n\n  const dcFirstArg = dcOrVars && 'enableEmulator' in dcOrVars;\n\n  if (dcFirstArg) {\n    dcInstance = dcOrVars as DataConnect;\n    realVars = vars as Variables;\n  } else {\n    dcInstance = getDataConnect(connectorConfig);\n    realVars = dcOrVars as Variables;\n  }\n\n  if (!dcInstance || (!realVars && variablesRequired)) {\n    throw new DataConnectError(Code.INVALID_ARGUMENT, 'Variables required.');\n  }\n\n  return { dc: dcInstance, vars: realVars };\n}\n\n/**\n * The generated SDK will allow the user to pass in either the variables or the data connect instance\n * with the variables, and/or options. This function validates the variables and returns back the\n * DataConnect instance and variables, and potentially options, based on the arguments passed in.\n *\n * Generated SDKs generated from versions 3.2.0 and higher of the Data Connect emulator binary are\n * in fact concerned with options, and will use this function to validate arguments.\n *\n * @param connectorConfig\n * @param dcOrVarsOrOptions\n * @param varsOrOptions\n * @param variablesRequired\n * @param options\n * @returns {DataConnect} and {Variables} instance, and optionally {ExecuteQueryOptions}\n * @internal\n */\nexport function validateArgsWithOptions<Variables extends object>(\n  connectorConfig: ConnectorConfig,\n  dcOrVarsOrOptions?: DataConnect | Variables | ExecuteQueryOptions,\n  varsOrOptions?: Variables | ExecuteQueryOptions,\n  options?: ExecuteQueryOptions,\n  hasVars?: boolean,\n  variablesRequired?: boolean\n): ParsedArgs<Variables> {\n  let dcInstance: DataConnect;\n  let realVars: Variables;\n  let realOptions: ExecuteQueryOptions;\n\n  const dcFirstArg = dcOrVarsOrOptions && 'enableEmulator' in dcOrVarsOrOptions;\n\n  if (dcFirstArg) {\n    dcInstance = dcOrVarsOrOptions as DataConnect;\n    if (hasVars) {\n      realVars = varsOrOptions as Variables;\n      realOptions = options as ExecuteQueryOptions;\n    } else {\n      realVars = undefined as unknown as Variables;\n      realOptions = varsOrOptions as ExecuteQueryOptions;\n    }\n  } else {\n    dcInstance = getDataConnect(connectorConfig);\n    if (hasVars) {\n      realVars = dcOrVarsOrOptions as Variables;\n      realOptions = varsOrOptions as ExecuteQueryOptions;\n    } else {\n      realVars = undefined as unknown as Variables;\n      realOptions = dcOrVarsOrOptions as ExecuteQueryOptions;\n    }\n  }\n\n  if (!dcInstance || (!realVars && variablesRequired)) {\n    throw new DataConnectError(Code.INVALID_ARGUMENT, 'Variables required.');\n  }\n\n  return { dc: dcInstance, vars: realVars, options: realOptions };\n}\n","/**\n * @license\n * Copyright 2025 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { QueryRef, QueryResult, toQueryRef } from '../../api/query';\nimport { SerializedRef } from '../../api/Reference';\nimport { DataConnectError, Code } from '../error';\n\nimport { getRefSerializer } from './QueryManager';\n\n/**\n * `OnCompleteSubscription`\n */\nexport type OnCompleteSubscription = () => void;\n/**\n * Representation of full observer options in `subscribe`\n */\nexport interface SubscriptionOptions<Data, Variables> {\n  onNext?: OnResultSubscription<Data, Variables>;\n  onErr?: OnErrorSubscription;\n  onComplete?: OnCompleteSubscription;\n}\n\n/**\n * Signature for `OnResultSubscription` for `subscribe`\n */\nexport type OnResultSubscription<Data, Variables> = (\n  res: QueryResult<Data, Variables>\n) => void;\n/**\n * Signature for `OnErrorSubscription` for `subscribe`\n */\nexport type OnErrorSubscription = (err?: DataConnectError) => void;\n/**\n * Signature for unsubscribe from `subscribe`\n */\nexport type QueryUnsubscribe = () => void;\n/**\n * Representation of user provided subscription options.\n */\nexport interface DataConnectSubscription<Data, Variables> {\n  userCallback: OnResultSubscription<Data, Variables>;\n  errCallback?: (e?: DataConnectError) => void;\n  unsubscribe: () => void;\n}\n\n/**\n * Subscribe to a `QueryRef`\n * @param queryRefOrSerializedResult query ref or serialized result.\n * @param observer observer object to use for subscribing.\n * @returns `SubscriptionOptions`\n */\nexport function subscribe<Data, Variables>(\n  queryRefOrSerializedResult:\n    | QueryRef<Data, Variables>\n    | SerializedRef<Data, Variables>,\n  observer: SubscriptionOptions<Data, Variables>\n): QueryUnsubscribe;\n/**\n * Subscribe to a `QueryRef`\n * @param queryRefOrSerializedResult query ref or serialized result.\n * @param onNext Callback to call when result comes back.\n * @param onError Callback to call when error gets thrown.\n * @param onComplete Called when subscription completes.\n * @returns `SubscriptionOptions`\n */\nexport function subscribe<Data, Variables>(\n  queryRefOrSerializedResult:\n    | QueryRef<Data, Variables>\n    | SerializedRef<Data, Variables>,\n  onNext: OnResultSubscription<Data, Variables>,\n  onError?: OnErrorSubscription,\n  onComplete?: OnCompleteSubscription\n): QueryUnsubscribe;\n/**\n * Subscribe to a `QueryRef`\n * @param queryRefOrSerializedResult query ref or serialized result.\n * @param observerOrOnNext observer object or next function.\n * @param onError Callback to call when error gets thrown.\n * @param onComplete Called when subscription completes.\n * @returns `SubscriptionOptions`\n */\nexport function subscribe<Data, Variables>(\n  queryRefOrSerializedResult:\n    | QueryRef<Data, Variables>\n    | SerializedRef<Data, Variables>,\n  observerOrOnNext:\n    | SubscriptionOptions<Data, Variables>\n    | OnResultSubscription<Data, Variables>,\n  onError?: OnErrorSubscription,\n  onComplete?: OnCompleteSubscription\n): QueryUnsubscribe {\n  let ref: QueryRef<Data, Variables>;\n  let initialCache: QueryResult<Data, Variables> | undefined;\n  if ('refInfo' in queryRefOrSerializedResult) {\n    const serializedRef: SerializedRef<Data, Variables> =\n      queryRefOrSerializedResult;\n    const { data, source, fetchTime } = serializedRef;\n\n    ref = toQueryRef(serializedRef);\n    initialCache = {\n      data,\n      source,\n      fetchTime,\n      ref,\n      toJSON: getRefSerializer(ref, data, source, fetchTime)\n    };\n  } else {\n    ref = queryRefOrSerializedResult;\n  }\n  let onResult: OnResultSubscription<Data, Variables> | undefined = undefined;\n  if (typeof observerOrOnNext === 'function') {\n    onResult = observerOrOnNext;\n  } else {\n    onResult = observerOrOnNext.onNext;\n    onError = observerOrOnNext.onErr;\n    onComplete = observerOrOnNext.onComplete;\n  }\n  if (!onResult) {\n    throw new DataConnectError(Code.INVALID_ARGUMENT, 'Must provide onNext');\n  }\n  return ref.dataConnect._queryManager.addSubscription(\n    ref,\n    onResult,\n    onComplete,\n    onError,\n    initialCache\n  );\n}\n","/**\n * @license\n * Copyright 2024 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n// eslint-disable-next-line import/no-extraneous-dependencies\nimport {\n  _registerComponent,\n  registerVersion,\n  SDK_VERSION\n} from '@firebase/app';\nimport { Component, ComponentType } from '@firebase/component';\n\nimport { name, version } from '../package.json';\nimport { setSDKVersion } from '../src/core/version';\n\nimport { DataConnect, ConnectorConfig } from './api/DataConnect';\nimport { Code, DataConnectError } from './core/error';\n\nexport function registerDataConnect(variant?: string): void {\n  setSDKVersion(SDK_VERSION);\n  _registerComponent(\n    new Component(\n      'data-connect',\n      (container, { instanceIdentifier: connectorConfigStr, options }) => {\n        const app = container.getProvider('app').getImmediate()!;\n        const authProvider = container.getProvider('auth-internal');\n        const appCheckProvider = container.getProvider('app-check-internal');\n        let newOpts = options as ConnectorConfig;\n        if (connectorConfigStr) {\n          newOpts = {\n            ...JSON.parse(connectorConfigStr),\n            ...newOpts\n          };\n        }\n        if (!app.options.projectId) {\n          throw new DataConnectError(\n            Code.INVALID_ARGUMENT,\n            'Project ID must be provided. Did you pass in a proper projectId to initializeApp?'\n          );\n        }\n        return new DataConnect(\n          app,\n          { ...newOpts, projectId: app.options.projectId! },\n          authProvider,\n          appCheckProvider\n        );\n      },\n      ComponentType.PUBLIC\n    ).setMultipleInstances(true)\n  );\n  registerVersion(name, version, variant);\n  // BUILD_TARGET will be replaced by values like esm, cjs, etc during the compilation\n  registerVersion(name, version, '__BUILD_TARGET__');\n}\n","/**\n * Firebase Data Connect\n *\n * @packageDocumentation\n */\n\n/**\n * @license\n * Copyright 2024 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { DataConnect } from './api/DataConnect';\nimport { registerDataConnect } from './register';\n\nexport * from './api';\nexport * from './api.browser';\n\nregisterDataConnect();\n\ndeclare module '@firebase/component' {\n  interface NameServiceMapping {\n    'data-connect': DataConnect;\n  }\n}\n"],"names":["FirebaseError","Error","constructor","code","message","customData","super","this","name","Object","setPrototypeOf","prototype","captureStackTrace","ErrorFactory","create","service","serviceName","errors","data","fullCode","template","replaceTemplate","replace","PATTERN","_","key","value","String","fullMessage","isCloudWorkstation","url","startsWith","URL","hostname","endsWith","Component","instanceFactory","type","multipleInstances","serviceProps","instantiationMode","onInstanceCreated","setInstantiationMode","mode","setMultipleInstances","setServiceProps","props","setInstanceCreatedCallback","callback","LogLevel","levelStringToEnum","debug","DEBUG","verbose","VERBOSE","info","INFO","warn","WARN","error","ERROR","silent","SILENT","defaultLogLevel","ConsoleMethod","defaultLogHandler","instance","logType","args","logLevel","now","Date","toISOString","method","console","SDK_VERSION","Code","OTHER","ALREADY_INITIALIZED","NOT_INITIALIZED","NOT_SUPPORTED","INVALID_ARGUMENT","PARTIAL_ERROR","UNAUTHORIZED","DataConnectError","toString","DataConnectOperationError","response","EntityDataObject","getServerValue","serverValues","globalID","referencedFrom","Set","getServerValues","toJSON","map","Array","from","fromJSON","json","edo","updateServerValue","requestedFrom","add","InMemoryCacheProvider","_keyId","edos","Map","resultTrees","setResultTree","queryId","rt","set","getResultTree","get","updateEntityData","entityData","getEntityData","globalId","has","close","Promise","resolve","GLOBAL_ID_KEY","EntityNode","scalars","references","objectLists","entityDataKeys","loadData","values","entityIds","acc","cacheProvider","undefined","isArray","hasOwnProperty","ids","objArray","scalarArray","index","entries","entityNode","push","length","impactedRefs","resultObject","EncodingMode","hydrated","assign","obj","fromJson","sdo","backingData","ResultTree","rootStub","maxAge","cachedAt","lastAccessed","_lastAccessed","isStale","getTime","updateMaxAge","maxAgeInSeconds","updateAccessed","getRootStub","ImpactedQueryRefsAccumulator","impacted","filter","ref","forEach","consumeEvents","events","clear","ResultTreeProcessor","hydrateResults","rootStubObject","dehydrateResults","DataConnectCache","authProvider","projectId","connectorConfig","host","cacheSettings","uid","addTokenChangeListener","async","newUid","getAuth","getUid","identifier","getIdentifier","initializeNewProviders","initialize","connector","location","generateSHA256Hash","input","TextEncoder","encode","hashBuffer","crypto","subtle","digest","Uint8Array","b","padStart","join","containsResultTree","getResultJSON","processor","resultTree","update","stubDataObject","maxAgeSeconds","MemoryStub","cacheId","AppCheckTokenProvider","app","appCheckProvider","_isFirebaseServerApp","settings","appCheckToken","serverAppAppCheckToken","appCheck","getImmediate","optional","then","catch","getToken","token","reject","setTimeout","listener","addTokenListener","logger","Logger","_logLevel","_logHandler","_userLogHandler","val","TypeError","setLogLevel","logHandler","userLogHandler","log","logDebug","msg","logError","FirebaseAuthProvider","_appName","_options","_authProvider","_auth","onInit","auth","forceRefresh","JSON","stringify","addAuthTokenListener","removeTokenChangeListener","removeAuthTokenListener","err","QUERY_STR","MUTATION_STR","SOURCE_SERVER","SOURCE_CACHE","populatePath","path","toUpdate","extension","curObj","slice","entityId","entityArr","i","_id","encoderImpl","decoderImpl","sortKeysForObj","o","keys","sort","reduce","accumulator","currentKey","getRefSerializer","queryRef","source","fetchTime","refInfo","variables","dataConnect","options","getSettings","setEncoder","encoder","setDecoder","decoder","s","parse","QueryManager","preferCacheResults","allowStale","cacheResult","fetchCacheResults","e","fetchServerResults","transport","dc","cache","callbacks","subscriptionCache","queue","waitForQueuedWrites","promise","updateSSR","updatedData","updateCache","result","publishCacheResultsToSubscribers","extensions","parseEntityIds","dataConnectExtensions","dataCopy","ret","updatedMaxAge","getMaxAgeFromExtensions","Number","substring","refType","addSubscription","onResultCallback","onCompleteCallback","onErrorCallback","initialCache","unsubscribe","newList","subscription","delete","invokeUnsubscribe","userCallback","errCallback","invokeSubscribe","makeSubscribeObserver","invokeQuery","originalExtensions","queryResult","getDataConnectExtensionsWithoutMaxAge","updatedKeys","publishDataToSubscribers","publishErrorToSubscribers","getFromResultTreeCache","getFromSubscriberCache","impactedQueries","query","newJson","enableEmulator","port","useEmulator","onData","handleStreamNotification","onDisconnect","reason","handleStreamDisconnect","onError","stringified","failureResponse","cb","CallerSdkTypeEnum","Base","Generated","TanstackReactCore","GeneratedReact","TanstackAngularCore","GeneratedAngular","getGoogApiClientValue","isUsingGen","callerSdkType","str","toLowerCase","AbstractDataConnectTransport","apiKey","appId","transportOptions","_isUsingGen","_callerSdkType","_host","_location","_connectorName","_secure","_project","_authToken","_appCheckToken","_lastToken","_isUsingEmulator","_port","sslEnabled","project","_serviceName","_connectorResourcePath","onAuthTokenChanged","isSecure","getWithAuth","forceToken","starterPromise","accessToken","withRetry","promiseFactory","retry","isNewToken","res","_setLastToken","lastToken","_setCallerSdkType","connectFetch","globalThis","fetch","dcFetch","body","signal","headers","fetchOptions","jsonResponse","credentials","getErrorMessage","status","PROD_HOST","addToken","newUrl","searchParams","append","RESTTransport","queryName","abortController","AbortController","endpointUrl","operationName","invokeMutation","mutationName","restUrlBuilder","projectConfig","baseUrl","observer","newToken","AbstractDataConnectStreamTransport","isPendingClose","idleTimeout","hasActiveSubscriptions","activeInvokeSubscribeRequests","size","hasActiveExecuteRequests","activeInvokeQueryRequests","activeInvokeMutationRequests","isUnableToConnect","requestNumber","queuedInvokeQueryRequests","executeRequestPromises","resumeRequestPromises","subscribeObservers","pendingCancellations","hasWaitedForInitialAuth","reconnectDelayMs","reconnectTimer","reconnectAttempts","removeOnlineEventListener","removeVisibilityChangeEventListener","onOnlineEventListener","cancelReconnect","attemptReconnect","onVisibilityChangeEventListener","doc","document","visibilityState","isFirstStreamMessage","lastSentAuthToken","registerBrowserEventListeners","addEventListener","removeEventListener","cleanupBrowserEventListeners","cleanupAndTerminate","cancelClose","rejectAllRequests","closeConnection","onCloseCallback","nextRequestId","trackInvokeMutationRequest","requestId","mapKey","executeBody","resolveFn","rejectFn","executeRequestPromise","responsePromise","activeRequests","trackInvokeSubscribeRequest","subscribeBody","cleanupInvokeQueryRequest","cleanupInvokeMutationRequest","executeRequests","updatedRequests","request","cleanupInvokeSubscribeRequest","clearTimeout","startReconnectBackoff","errorString","delay","Math","min","jitter","random","ensureConnection","retriggerActiveRequests","sendRequestMessage","requestBody","shouldIncludeAuth","onConnectionReady","startIdleCloseTimeout","rejectAllMutationsOnReconnect","requests","onStreamClose","prepareMessage","preparedRequestBody","streamIsReady","prepared","sendMessage","getMapKey","sortedVariables","sortObjectKeys","sortedObj","queueInvokeQueryRequest","executeOrResumeQuery","existingQueued","queuedInvokeOperationPromise","activeSubscription","resume","execute","finally","onInvokeQueryRequestFulfilled","cancelSubscription","queuedRequestPromise","activeRequestKey","existingSubscribe","subscribe","subscribeRequest","cancelBody","cancel","oldAuthToken","oldAuthUid","authUid","newAuthUid","handleResponse","handleInvokeOperationResponse","resumePromise","connectWebSocket","WebSocket","WebSocketTransport","connection","connectionAttempt","websocketUrlBuilder","decodeBinaryResponse","TextDecoder","decode","readyState","OPEN","ws","binaryType","onopen","onerror","event","handleError","onmessage","ev","handleWebSocketMessage","onclose","handleWebsocketDisconnect","openConnection","MAX_BYTES","buf","read","encodeInto","truncatedReason","send","parseWebSocketData","dataIsString","webSocketMessage","DataConnectTransportManager","isUsingEmulator","restTransport","initStreamTransport","streamTransport","executeShouldUseStream","mutationRef","dcInstance","setInitialized","MutationManager","_transport","_inflight","executeMutation","withRefPromise","toLocaleString","removePromise","_mutationManager","parseOptions","fullHost","protocol","hostName","split","portAsString","DataConnect","dataConnectOptions","_appCheckProvider","isEmulator","_initialized","_isUsingGeneratedSdk","process","env","_transportOptions","getCache","_useGeneratedSdk","_delete","_removeServiceInstance","copy","setCacheSettings","_cacheSettings","_transportClass","_authTokenProvider","_appCheckTokenProvider","_queryManager","areTransportOptionsEqual","transportOptions1","transportOptions2","connectDataConnectEmulator","pingServer","endpoint","ok","getDataConnect","appOrConnectorConfig","settingsOrConnectorConfig","realSettings","getApp","serializedOptions","sortedSerialized","fromEntries","provider","_getProvider","isInitialized","getOptions","validateDCOptions","instanceIdentifier","dcOptions","field","terminate","StorageType","MEMORY","makeMemoryCacheProvider","QueryFetchPolicy","PREFER_CACHE","CACHE_ONLY","SERVER_ONLY","executeQuery","queryManager","fetchPolicy","toQueryRef","serializedRef","validateArgs","dcOrVars","vars","variablesRequired","realVars","validateArgsWithOptions","dcOrVarsOrOptions","varsOrOptions","hasVars","realOptions","queryRefOrSerializedResult","observerOrOnNext","onComplete","onResult","onNext","onErr","registerDataConnect","variant","setSDKVersion","version","_registerComponent","container","connectorConfigStr","getProvider","newOpts","registerVersion"],"mappings":"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","preExistingComment":"firebase-data-connect.js.map"}