From 15304a80fe61a8bd744090a440247aa33495508c Mon Sep 17 00:00:00 2001 From: CoolElectronics Date: Thu, 24 Aug 2023 15:21:24 -0400 Subject: [PATCH] add npm stuff, `dist/` folder --- .gitignore | 2 +- dist/Transport.d.ts | 8 + dist/client.cjs | 18433 ++++++++++++++++++++++++++ dist/client.mjs | 18417 +++++++++++++++++++++++++ dist/client/src/AdriftClient.d.ts | 8 + dist/client/src/Connection.d.ts | 36 + dist/client/src/DevWsTransport.d.ts | 8 + dist/client/src/RTCTransport.d.ts | 23 + dist/client/src/SignalFirebase.d.ts | 3 + dist/client/src/index.d.ts | 6 + dist/index.d.ts | 57 + dist/protocol.cjs | 69 + dist/protocol.mjs | 47 + dist/protocol/src/Transport.d.ts | 8 + dist/protocol/src/index.d.ts | 57 + esbuild.package.js | 22 + frontend/src/App.svelte | 1 - package.json | 41 +- pnpm-lock.yaml | 13706 +++++++++++++++++++ protocol/package.json | 2 +- server/package.json | 2 +- tsconfig.json | 6 + 22 files changed, 50951 insertions(+), 11 deletions(-) create mode 100644 dist/Transport.d.ts create mode 100644 dist/client.cjs create mode 100644 dist/client.mjs create mode 100644 dist/client/src/AdriftClient.d.ts create mode 100644 dist/client/src/Connection.d.ts create mode 100644 dist/client/src/DevWsTransport.d.ts create mode 100644 dist/client/src/RTCTransport.d.ts create mode 100644 dist/client/src/SignalFirebase.d.ts create mode 100644 dist/client/src/index.d.ts create mode 100644 dist/index.d.ts create mode 100644 dist/protocol.cjs create mode 100644 dist/protocol.mjs create mode 100644 dist/protocol/src/Transport.d.ts create mode 100644 dist/protocol/src/index.d.ts create mode 100644 esbuild.package.js create mode 100644 pnpm-lock.yaml create mode 100644 tsconfig.json diff --git a/.gitignore b/.gitignore index 30d7b7a..9d34859 100644 --- a/.gitignore +++ b/.gitignore @@ -2,7 +2,7 @@ node_modules dist.js dist.js.map dist.html -dist/ +*/dist/ admin-creds.json server/config.json .firebaserrc diff --git a/dist/Transport.d.ts b/dist/Transport.d.ts new file mode 100644 index 0000000..56ed940 --- /dev/null +++ b/dist/Transport.d.ts @@ -0,0 +1,8 @@ +export declare abstract class Transport { + onopen: () => void; + onclose: () => void; + ondata: (data: ArrayBuffer) => void; + constructor(onopen: () => void, onclose: () => void); + abstract send(data: ArrayBuffer): void; + abstract close(): void; +} diff --git a/dist/client.cjs b/dist/client.cjs new file mode 100644 index 0000000..6cea72a --- /dev/null +++ b/dist/client.cjs @@ -0,0 +1,18433 @@ +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __export = (target, all) => { + for (var name4 in all) + __defProp(target, name4, { get: all[name4], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// client/src/index.ts +var src_exports = {}; +__export(src_exports, { + AdriftBareClient: () => AdriftBareClient, + Connection: () => Connection, + DevWsTransport: () => DevWsTransport, + RTCTransport: () => RTCTransport, + SignalFirebase: () => SignalFirebase_exports, + downloadShortcut: () => downloadShortcut +}); +module.exports = __toCommonJS(src_exports); + +// node_modules/.pnpm/uuid@9.0.0/node_modules/uuid/dist/esm-browser/rng.js +var getRandomValues; +var rnds8 = new Uint8Array(16); +function rng() { + if (!getRandomValues) { + getRandomValues = typeof crypto !== "undefined" && crypto.getRandomValues && crypto.getRandomValues.bind(crypto); + if (!getRandomValues) { + throw new Error("crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported"); + } + } + return getRandomValues(rnds8); +} + +// node_modules/.pnpm/uuid@9.0.0/node_modules/uuid/dist/esm-browser/stringify.js +var byteToHex = []; +for (let i = 0; i < 256; ++i) { + byteToHex.push((i + 256).toString(16).slice(1)); +} +function unsafeStringify(arr, offset = 0) { + return (byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + "-" + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + "-" + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + "-" + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + "-" + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]]).toLowerCase(); +} + +// node_modules/.pnpm/uuid@9.0.0/node_modules/uuid/dist/esm-browser/native.js +var randomUUID = typeof crypto !== "undefined" && crypto.randomUUID && crypto.randomUUID.bind(crypto); +var native_default = { + randomUUID +}; + +// node_modules/.pnpm/uuid@9.0.0/node_modules/uuid/dist/esm-browser/v4.js +function v4(options, buf, offset) { + if (native_default.randomUUID && !buf && !options) { + return native_default.randomUUID(); + } + options = options || {}; + const rnds = options.random || (options.rng || rng)(); + rnds[6] = rnds[6] & 15 | 64; + rnds[8] = rnds[8] & 63 | 128; + if (buf) { + offset = offset || 0; + for (let i = 0; i < 16; ++i) { + buf[offset + i] = rnds[i]; + } + return buf; + } + return unsafeStringify(rnds); +} +var v4_default = v4; + +// node_modules/.pnpm/file+bare-client-custom/node_modules/bare-client-custom/dist/index.js +var WebSocket2 = globalThis.WebSocket; +var Request = globalThis.Request; +var Response2 = globalThis.Response; +var WebSocketFields = { + prototype: { + send: WebSocket2.prototype.send + }, + CLOSED: WebSocket2.CLOSED, + CLOSING: WebSocket2.CLOSING, + CONNECTING: WebSocket2.CONNECTING, + OPEN: WebSocket2.OPEN +}; +var statusEmpty = [101, 204, 205, 304]; +var Client = class { +}; +var RemoteClient = class extends Client { + callbacks = {}; + uid = v4_default(); + constructor() { + super(); + if (!("ServiceWorkerGlobalScope" in self)) { + throw new TypeError("Attempt to construct RemoteClient from outside a service worker"); + } + addEventListener("message", (event) => { + if (event.data.__remote_target === this.uid) { + const callback = this.callbacks[event.data.__remote_id]; + callback(event.data.__remote_value); + } + }); + } + async send(message, id) { + const clients = await self.clients.matchAll(); + if (clients.length < 1) + throw new Error("no available clients"); + for (const client of clients) { + client.postMessage({ + __remote_target: this.uid, + __remote_id: id, + __remote_value: message + }); + } + } + async sendWithResponse(message) { + const id = v4_default(); + return new Promise((resolve) => { + this.callbacks[id] = resolve; + this.send(message, id); + }); + } + connect(remote, protocols, getRequestHeaders, onMeta, onReadyState) { + return new WebSocket2(""); + } + async request(method, requestHeaders, body, remote, cache, duplex, signal) { + const response = await this.sendWithResponse({ + type: "request", + options: { + method, + requestHeaders, + body, + remote: remote.toString() + } + }); + const result = new Response2(statusEmpty.includes(response.status) ? void 0 : response.body, { + status: response.status, + statusText: response.statusText ?? void 0, + headers: new Headers(response.headers) + }); + result.rawHeaders = response.headers; + result.rawResponse = response; + return result; + } +}; +var getRealReadyState = Object.getOwnPropertyDescriptor(WebSocket2.prototype, "readyState").get; +self.BCC_VERSION = "1.2.1"; +console.warn("BCC_VERSION: " + self.BCC_VERSION); +function setBareClientImplementation(implementation) { + self.gBareClientImplementation = implementation; +} +if ("ServiceWorkerGlobalScope" in self) { + setBareClientImplementation(new RemoteClient()); +} else { + let parent = self; + console.log("attempting to find an implementation"); + for (let i = 0; i < 10; i++) { + try { + parent = parent.parent; + if (parent && parent["gBareClientImplementation"]) { + console.warn("found implementation on parent"); + setBareClientImplementation(parent["gBareClientImplementation"]); + break; + } + } catch (e) { + console.log("could not find implementation"); + break; + } + } +} + +// protocol/src/Transport.ts +var Transport = class { + constructor(onopen, onclose) { + this.onopen = onopen; + this.onclose = onclose; + } + ondata = () => { + }; +}; + +// protocol/src/index.ts +var C2SRequestTypes = { + HTTPRequestStart: 0, + HTTPRequestChunk: 1, + HTTPRequestEnd: 2, + WSOpen: 3, + WSClose: 4, + WSSendText: 5, + WSSendBinary: 6 +}; +var S2CRequestTypes = { + HTTPResponseStart: 0, + HTTPResponseChunk: 1, + HTTPResponseEnd: 2, + WSOpen: 3, + WSClose: 4, + WSTextStart: 5, + WSBinaryStart: 6, + WSDataChunk: 7, + WSDataEnd: 8, + WSError: 9 +}; +var MAX_CHUNK_SIZE = 12 * 1024; +var S2C_HELLO_OK = ":3"; +var C2S_HELLO = "haiii "; +var S2C_HELLO_ERR = ":< "; +var PROTOCOL_VERSION = "3.0"; + +// client/src/AdriftClient.ts +var NULL_BODY_STATUSES = [101, 103, 204, 205, 304]; +function createBodyStream(body, arrayBufferImpl) { + if (body === null || typeof body === "undefined") + return null; + if (typeof body === "string") { + body = new TextEncoder().encode(body); + } + if (window.ArrayBuffer.isView(body)) { + body = body.buffer.slice( + body.byteOffset, + body.byteOffset + body.byteLength + ); + } + if (body instanceof window.ArrayBuffer) { + if (body.byteLength == 0) { + return null; + } + let remaining = body; + return new ReadableStream({ + type: "bytes", + pull: (controller) => { + if (remaining.byteLength <= 0) { + return controller.close(); + } + const current = remaining.slice(0, MAX_CHUNK_SIZE); + remaining = remaining.slice(MAX_CHUNK_SIZE); + controller.enqueue(new Uint8Array(current)); + } + }); + } + if (body instanceof FormData) { + throw new Error("formdata todo"); + } + const transformer = () => new TransformStream({ + transform: async (chunk, controller) => { + if (typeof chunk === "string") { + chunk = new TextEncoder().encode(chunk); + } + if (chunk instanceof Blob) { + chunk = await chunk.arrayBuffer(); + } + if (window.ArrayBuffer.isView(chunk)) { + chunk = chunk.buffer.slice( + chunk.byteOffset, + chunk.byteOffset + chunk.byteLength + ); + } + if (!(chunk instanceof window.ArrayBuffer)) { + console.error({ chunk }); + throw new Error("Invalid type read from body stream: " + chunk); + } + let current = null; + let remaining = chunk; + do { + current = remaining.slice(0, MAX_CHUNK_SIZE); + remaining = remaining.slice(MAX_CHUNK_SIZE); + controller.enqueue(new Uint8Array(current)); + } while (remaining.byteLength > 0); + } + }); + if (body instanceof ReadableStream) { + return body.pipeThrough(transformer()); + } + if (body instanceof Blob) { + return body.stream().pipeThrough(transformer()); + } + throw new Error("Unexpected body type: " + body); +} +var AdriftBareClient = class extends Client { + constructor(connection) { + super(); + this.connection = connection; + } + async request(method, requestHeaders, body, remote, cache, duplex, signal, arrayBufferImpl) { + const bodyStream = createBodyStream(body, arrayBufferImpl); + let { payload, body: respRawBody } = await this.connection.httprequest( + { + method, + requestHeaders, + remote + }, + bodyStream + ); + const headers = new Headers(); + for (const [header, values] of Object.entries(payload.headers)) { + for (const value of values) { + headers.append(header, value); + } + } + let respBody = respRawBody; + if (respBody.byteLength == 0 || NULL_BODY_STATUSES.includes(payload.status)) { + respBody = null; + } + return new Response(respBody, { + status: payload.status, + statusText: payload.statusText, + headers + }); + } + connect(remote, protocols, getRequestHeaders, onMeta, onReadyState, webSocketImpl, arrayBufferImpl) { + const ws = new webSocketImpl("wss:null", protocols); + let initalCloseHappened = false; + ws.addEventListener("close", (e) => { + if (!initalCloseHappened) { + onReadyState(WebSocket.CONNECTING); + e.stopImmediatePropagation(); + initalCloseHappened = true; + } + }); + let initialErrorHappened = false; + ws.addEventListener("error", (e) => { + if (!initialErrorHappened) { + onReadyState(WebSocket.CONNECTING); + e.stopImmediatePropagation(); + initialErrorHappened = true; + } + }); + let { send, close } = this.connection.wsconnect( + remote, + protocols, + (protocol) => { + onReadyState(WebSocket.OPEN); + ws.__defineGetter__("protocol", () => { + return protocol; + }); + ws.dispatchEvent(new Event("open")); + }, + (code, reason, wasClean) => { + onReadyState(WebSocket.CLOSED); + ws.dispatchEvent(new CloseEvent("close", { code, reason, wasClean })); + }, + async (stream, isBinary) => { + let data = await new Response( + stream + ).arrayBuffer(); + data.__proto__ = arrayBufferImpl.prototype; + if (!isBinary) { + try { + data = new TextDecoder().decode(); + } catch (e) { + console.error(e); + return; + } + } + ws.dispatchEvent(new MessageEvent("message", { data })); + }, + (message) => { + console.log({ message }); + ws.dispatchEvent(new ErrorEvent("error", { message })); + }, + arrayBufferImpl + ); + ws.send = (data) => { + send(data); + }; + ws.close = (code, reason) => { + close(code, reason); + onReadyState(WebSocket.CLOSING); + }; + return ws; + } +}; + +// client/src/Connection.ts +ReadableStream.prototype[Symbol.asyncIterator] = async function* () { + const reader = this.getReader(); + try { + while (true) { + const { done, value } = await reader.read(); + if (done) + return; + yield value; + } + } finally { + reader.releaseLock(); + } +}; +var Connection = class _Connection { + constructor(transport) { + this.transport = transport; + this.initialized = false; + this.requestCallbacks = {}; + this.openRequestStreams = {}; + this.openingSockets = {}; + this.openSockets = {}; + this.wsMsgStreams = {}; + this.counter = 0; + transport.ondata = _Connection.uninitializedError; + } + static uninitializedError() { + throw new Error("Connection not initialized"); + } + async initialize() { + const onDataPromise = () => { + return new Promise((res) => { + this.transport.ondata = res; + }); + }; + this.transport.send(new TextEncoder().encode(C2S_HELLO + PROTOCOL_VERSION)); + const msg = await onDataPromise(); + const msgText = new TextDecoder().decode(msg); + if (msgText === S2C_HELLO_OK) { + this.transport.ondata = this.ondata.bind(this); + this.initialized = true; + } else if (msgText.startsWith(S2C_HELLO_ERR)) { + const expectedVersion = msgText.slice(S2C_HELLO_ERR.length); + throw new Error( + `We are running protocol version ${PROTOCOL_VERSION}, but server expected ${expectedVersion}` + ); + } else { + throw new Error("Unexpected server hello response"); + } + } + nextSeq() { + return ++this.counter; + } + ondata(data) { + if (!this.initialized) + return; + let cursor = 0; + const view = new DataView(data); + let requestID = view.getUint16(cursor); + cursor += 2; + let requestType = view.getUint8(cursor); + cursor += 1; + const msgText = () => new TextDecoder().decode(data.slice(cursor)); + const msgJSON = () => JSON.parse(msgText()); + switch (requestType) { + case S2CRequestTypes.HTTPResponseStart: + const payload = msgJSON(); + const stream = new ReadableStream({ + start: (controller) => { + this.openRequestStreams[requestID] = controller; + }, + pull: (controller) => { + }, + cancel: () => { + } + }); + this.requestCallbacks[requestID]({ payload, body: stream }); + delete this.requestCallbacks[requestID]; + break; + case S2CRequestTypes.HTTPResponseChunk: + this.openRequestStreams[requestID]?.enqueue( + new Uint8Array(data.slice(cursor)) + ); + break; + case S2CRequestTypes.HTTPResponseEnd: + this.openRequestStreams[requestID]?.close(); + delete this.openRequestStreams[requestID]; + break; + case S2CRequestTypes.WSOpen: { + const socketMeta = this.openingSockets[requestID]; + if (!socketMeta) + return; + const payload2 = msgJSON(); + delete this.openingSockets[requestID]; + this.openSockets[requestID] = socketMeta; + setTimeout(() => socketMeta.onopen(payload2.protocol)); + break; + } + case S2CRequestTypes.WSBinaryStart: + case S2CRequestTypes.WSTextStart: { + const socketMeta = this.openSockets[requestID]; + if (!socketMeta) + return; + const stream2 = new ReadableStream({ + start: (controller) => { + this.wsMsgStreams[requestID] = controller; + }, + pull: (constroller) => { + }, + cancel: () => { + } + }); + setTimeout( + () => socketMeta.onmessage( + stream2, + requestType === S2CRequestTypes.WSBinaryStart ? true : requestType === S2CRequestTypes.WSTextStart ? false : (() => { + throw new Error("unreachable"); + })() + ) + ); + break; + } + case S2CRequestTypes.WSDataChunk: { + const stream2 = this.wsMsgStreams[requestID]; + stream2?.enqueue(new Uint8Array(data.slice(cursor))); + break; + } + case S2CRequestTypes.WSDataEnd: { + const stream2 = this.wsMsgStreams[requestID]; + stream2?.close(); + break; + } + case S2CRequestTypes.WSClose: { + const socketMeta = this.openingSockets[requestID] || this.openSockets[requestID]; + if (!socketMeta) + return; + const payload2 = msgJSON(); + setTimeout( + () => socketMeta.onclose( + payload2.code || 1005, + payload2.reason || "", + "wasClean" in payload2 ? Boolean(payload2.wasClean) : false + ) + ); + delete this.openingSockets[requestID]; + delete this.openSockets[requestID]; + break; + } + case S2CRequestTypes.WSError: { + const socketMeta = this.openingSockets[requestID] || this.openSockets[requestID]; + if (!socketMeta) + return; + const payload2 = msgJSON(); + setTimeout(() => socketMeta.onerror(payload2.message)); + break; + } + default: + break; + } + } + async send(requestID, type, data) { + if (!this.initialized) { + _Connection.uninitializedError(); + } + let header = new window.ArrayBuffer(2 + 1); + let view = new DataView(header); + let cursor = 0; + view.setUint16(cursor, requestID); + cursor += 2; + view.setUint8(cursor, type); + cursor += 1; + let buf = header; + if (data) { + buf = await new Blob([header, data]).arrayBuffer(); + } + this.transport.send(buf); + } + httprequest(data, body) { + if (!this.initialized) { + _Connection.uninitializedError(); + } + const payload = { ...data, hasBody: Boolean(body) }; + let json = JSON.stringify(payload); + return new Promise(async (resolve) => { + let seq = this.nextSeq(); + this.requestCallbacks[seq] = resolve; + await this.send(seq, C2SRequestTypes.HTTPRequestStart, new Blob([json])); + if (payload.hasBody) { + for await (const chunk of body) { + await this.send( + seq, + C2SRequestTypes.HTTPRequestChunk, + new Uint8Array(chunk) + ); + } + await this.send(seq, C2SRequestTypes.HTTPRequestEnd); + } + }); + } + wsconnect(url, protocols, onopen, onclose, onmessage, onerror, arrayBufferImpl) { + if (!this.initialized) { + _Connection.uninitializedError(); + } + const payload = { url: url.toString(), protocols }; + const payloadJSON = JSON.stringify(payload); + let seq = this.nextSeq(); + const closeWithError = () => onclose(1006, "", false); + this.send( + seq, + C2SRequestTypes.WSOpen, + new TextEncoder().encode(payloadJSON) + ).catch((e) => { + console.error(e); + closeWithError(); + }); + this.openingSockets[seq] = { + onopen, + onmessage, + onclose, + onerror + }; + return { + send: (data) => { + if (!this.openSockets[seq]) { + throw new Error("send on closed socket"); + } + const cleanup = (e) => { + console.error(e); + delete this.openSockets[seq]; + }; + if (typeof data === "string") { + this.send( + seq, + C2SRequestTypes.WSSendText, + new TextEncoder().encode(data) + ).catch(cleanup); + return; + } + if (data instanceof arrayBufferImpl) { + this.send(seq, C2SRequestTypes.WSSendBinary, data).catch(cleanup); + return; + } + if (arrayBufferImpl.isView(data)) { + this.send( + seq, + C2SRequestTypes.WSSendBinary, + data.buffer.slice( + data.byteOffset, + data.byteOffset + data.byteLength + ) + ).catch(cleanup); + return; + } + console.error({ data }); + throw new Error("Unexpected type passed to send"); + }, + close: (code, reason) => { + const payload2 = { code, reason }; + const payloadJSON2 = JSON.stringify(payload2); + this.send( + seq, + C2SRequestTypes.WSClose, + new TextEncoder().encode(payloadJSON2) + ).catch((e) => { + console.error(e); + }); + delete this.openSockets[seq]; + } + }; + } +}; + +// client/src/DevWsTransport.ts +var DevWsTransport = class extends Transport { + constructor(onopen, onclose) { + super(onopen, onclose); + this.ws = new WebSocket("ws://localhost:3000/dev-ws"); + this.ws.binaryType = "arraybuffer"; + this.ws.onopen = onopen; + this.ws.onclose = onclose; + this.ws.onmessage = this.onmessage.bind(this); + } + onmessage(msg) { + if (msg.data instanceof window.ArrayBuffer) { + this.ondata(msg.data); + return; + } + } + send(data) { + this.ws.send(data); + } + close() { + this.ws.close(); + } +}; + +// client/src/RTCTransport.ts +var rtcConf = { + iceServers: [ + { + urls: "stun:stun.l.google.com:19302" + } + ] +}; +var RTCTransport = class extends Transport { + constructor(onopen, onclose, onconnectionstatechange, onsignalingstatechange, onicegatheringstatechange) { + super(onopen, onclose); + this.onopen = onopen; + this.onclose = onclose; + this.onconnectionstatechange = onconnectionstatechange; + this.onsignalingstatechange = onsignalingstatechange; + this.onicegatheringstatechange = onicegatheringstatechange; + this.peer = new RTCPeerConnection(rtcConf); + this.peer.onconnectionstatechange = onconnectionstatechange; + this.peer.onsignalingstatechange = onsignalingstatechange; + this.peer.oniceconnectionstatechange = (event) => { + console.log("ICE connection state:", this.peer.iceConnectionState); + if (this.peer.iceConnectionState == "disconnected" || this.peer.iceConnectionState == "failed") { + console.log("disconnected"); + onclose(); + } + }; + this.peer.onicegatheringstatechange = onicegatheringstatechange; + this.dataChannel = this.peer.createDataChannel("host-server"); + this.dataChannel.onopen = onopen; + this.dataChannel.binaryType = "arraybuffer"; + this.dataChannel.onclose = onclose; + this.dataChannel.onmessage = async (event) => { + let buf = event.data; + this.ondata(buf); + }; + } + send(data) { + this.dataChannel.send(data); + } + close() { + this.dataChannel.close(); + } + async createOffer() { + const localCandidates = []; + let readyPromise = new Promise((resolve, reject) => { + this.peer.onicecandidate = async (event) => { + if (event.candidate) { + localCandidates.push(event.candidate); + return; + } + resolve({ offer, localCandidates }); + }; + }); + const offer = await this.peer.createOffer(); + await this.peer.setLocalDescription(offer); + return readyPromise; + } + async answer(answer, candidates) { + await this.peer.setRemoteDescription(answer); + for (let candidate of candidates) { + await this.peer.addIceCandidate(candidate); + } + } +}; + +// client/src/SignalFirebase.ts +var SignalFirebase_exports = {}; +__export(SignalFirebase_exports, { + signalAccount: () => signalAccount, + signalSwarm: () => signalSwarm +}); + +// node_modules/.pnpm/@firebase+util@1.9.3/node_modules/@firebase/util/dist/index.esm2017.js +var CONSTANTS = { + /** + * @define {boolean} Whether this is the client Node.js SDK. + */ + NODE_CLIENT: false, + /** + * @define {boolean} Whether this is the Admin Node.js SDK. + */ + NODE_ADMIN: false, + /** + * Firebase SDK Version + */ + SDK_VERSION: "${JSCORE_VERSION}" +}; +var assert = function(assertion, message) { + if (!assertion) { + throw assertionError(message); + } +}; +var assertionError = function(message) { + return new Error("Firebase Database (" + CONSTANTS.SDK_VERSION + ") INTERNAL ASSERT FAILED: " + message); +}; +var stringToByteArray$1 = function(str) { + const out = []; + let p = 0; + for (let i = 0; i < str.length; i++) { + let c = str.charCodeAt(i); + if (c < 128) { + out[p++] = c; + } else if (c < 2048) { + out[p++] = c >> 6 | 192; + out[p++] = c & 63 | 128; + } else if ((c & 64512) === 55296 && i + 1 < str.length && (str.charCodeAt(i + 1) & 64512) === 56320) { + c = 65536 + ((c & 1023) << 10) + (str.charCodeAt(++i) & 1023); + out[p++] = c >> 18 | 240; + out[p++] = c >> 12 & 63 | 128; + out[p++] = c >> 6 & 63 | 128; + out[p++] = c & 63 | 128; + } else { + out[p++] = c >> 12 | 224; + out[p++] = c >> 6 & 63 | 128; + out[p++] = c & 63 | 128; + } + } + return out; +}; +var byteArrayToString = function(bytes) { + const out = []; + let pos = 0, c = 0; + while (pos < bytes.length) { + const c1 = bytes[pos++]; + if (c1 < 128) { + out[c++] = String.fromCharCode(c1); + } else if (c1 > 191 && c1 < 224) { + const c2 = bytes[pos++]; + out[c++] = String.fromCharCode((c1 & 31) << 6 | c2 & 63); + } else if (c1 > 239 && c1 < 365) { + const c2 = bytes[pos++]; + const c3 = bytes[pos++]; + const c4 = bytes[pos++]; + const u = ((c1 & 7) << 18 | (c2 & 63) << 12 | (c3 & 63) << 6 | c4 & 63) - 65536; + out[c++] = String.fromCharCode(55296 + (u >> 10)); + out[c++] = String.fromCharCode(56320 + (u & 1023)); + } else { + const c2 = bytes[pos++]; + const c3 = bytes[pos++]; + out[c++] = String.fromCharCode((c1 & 15) << 12 | (c2 & 63) << 6 | c3 & 63); + } + } + return out.join(""); +}; +var base64 = { + /** + * Maps bytes to characters. + */ + byteToCharMap_: null, + /** + * Maps characters to bytes. + */ + charToByteMap_: null, + /** + * Maps bytes to websafe characters. + * @private + */ + byteToCharMapWebSafe_: null, + /** + * Maps websafe characters to bytes. + * @private + */ + charToByteMapWebSafe_: null, + /** + * Our default alphabet, shared between + * ENCODED_VALS and ENCODED_VALS_WEBSAFE + */ + ENCODED_VALS_BASE: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", + /** + * Our default alphabet. Value 64 (=) is special; it means "nothing." + */ + get ENCODED_VALS() { + return this.ENCODED_VALS_BASE + "+/="; + }, + /** + * Our websafe alphabet. + */ + get ENCODED_VALS_WEBSAFE() { + return this.ENCODED_VALS_BASE + "-_."; + }, + /** + * Whether this browser supports the atob and btoa functions. This extension + * started at Mozilla but is now implemented by many browsers. We use the + * ASSUME_* variables to avoid pulling in the full useragent detection library + * but still allowing the standard per-browser compilations. + * + */ + HAS_NATIVE_SUPPORT: typeof atob === "function", + /** + * Base64-encode an array of bytes. + * + * @param input An array of bytes (numbers with + * value in [0, 255]) to encode. + * @param webSafe Boolean indicating we should use the + * alternative alphabet. + * @return The base64 encoded string. + */ + encodeByteArray(input, webSafe) { + if (!Array.isArray(input)) { + throw Error("encodeByteArray takes an array as a parameter"); + } + this.init_(); + const byteToCharMap = webSafe ? this.byteToCharMapWebSafe_ : this.byteToCharMap_; + const output = []; + for (let i = 0; i < input.length; i += 3) { + const byte1 = input[i]; + const haveByte2 = i + 1 < input.length; + const byte2 = haveByte2 ? input[i + 1] : 0; + const haveByte3 = i + 2 < input.length; + const byte3 = haveByte3 ? input[i + 2] : 0; + const outByte1 = byte1 >> 2; + const outByte2 = (byte1 & 3) << 4 | byte2 >> 4; + let outByte3 = (byte2 & 15) << 2 | byte3 >> 6; + let outByte4 = byte3 & 63; + if (!haveByte3) { + outByte4 = 64; + if (!haveByte2) { + outByte3 = 64; + } + } + output.push(byteToCharMap[outByte1], byteToCharMap[outByte2], byteToCharMap[outByte3], byteToCharMap[outByte4]); + } + return output.join(""); + }, + /** + * Base64-encode a string. + * + * @param input A string to encode. + * @param webSafe If true, we should use the + * alternative alphabet. + * @return The base64 encoded string. + */ + encodeString(input, webSafe) { + if (this.HAS_NATIVE_SUPPORT && !webSafe) { + return btoa(input); + } + return this.encodeByteArray(stringToByteArray$1(input), webSafe); + }, + /** + * Base64-decode a string. + * + * @param input to decode. + * @param webSafe True if we should use the + * alternative alphabet. + * @return string representing the decoded value. + */ + decodeString(input, webSafe) { + if (this.HAS_NATIVE_SUPPORT && !webSafe) { + return atob(input); + } + return byteArrayToString(this.decodeStringToByteArray(input, webSafe)); + }, + /** + * Base64-decode a string. + * + * In base-64 decoding, groups of four characters are converted into three + * bytes. If the encoder did not apply padding, the input length may not + * be a multiple of 4. + * + * In this case, the last group will have fewer than 4 characters, and + * padding will be inferred. If the group has one or two characters, it decodes + * to one byte. If the group has three characters, it decodes to two bytes. + * + * @param input Input to decode. + * @param webSafe True if we should use the web-safe alphabet. + * @return bytes representing the decoded value. + */ + decodeStringToByteArray(input, webSafe) { + this.init_(); + const charToByteMap = webSafe ? this.charToByteMapWebSafe_ : this.charToByteMap_; + const output = []; + for (let i = 0; i < input.length; ) { + const byte1 = charToByteMap[input.charAt(i++)]; + const haveByte2 = i < input.length; + const byte2 = haveByte2 ? charToByteMap[input.charAt(i)] : 0; + ++i; + const haveByte3 = i < input.length; + const byte3 = haveByte3 ? charToByteMap[input.charAt(i)] : 64; + ++i; + const haveByte4 = i < input.length; + const byte4 = haveByte4 ? charToByteMap[input.charAt(i)] : 64; + ++i; + if (byte1 == null || byte2 == null || byte3 == null || byte4 == null) { + throw new DecodeBase64StringError(); + } + const outByte1 = byte1 << 2 | byte2 >> 4; + output.push(outByte1); + if (byte3 !== 64) { + const outByte2 = byte2 << 4 & 240 | byte3 >> 2; + output.push(outByte2); + if (byte4 !== 64) { + const outByte3 = byte3 << 6 & 192 | byte4; + output.push(outByte3); + } + } + } + return output; + }, + /** + * Lazy static initialization function. Called before + * accessing any of the static map variables. + * @private + */ + init_() { + if (!this.byteToCharMap_) { + this.byteToCharMap_ = {}; + this.charToByteMap_ = {}; + this.byteToCharMapWebSafe_ = {}; + this.charToByteMapWebSafe_ = {}; + for (let i = 0; i < this.ENCODED_VALS.length; i++) { + this.byteToCharMap_[i] = this.ENCODED_VALS.charAt(i); + this.charToByteMap_[this.byteToCharMap_[i]] = i; + this.byteToCharMapWebSafe_[i] = this.ENCODED_VALS_WEBSAFE.charAt(i); + this.charToByteMapWebSafe_[this.byteToCharMapWebSafe_[i]] = i; + if (i >= this.ENCODED_VALS_BASE.length) { + this.charToByteMap_[this.ENCODED_VALS_WEBSAFE.charAt(i)] = i; + this.charToByteMapWebSafe_[this.ENCODED_VALS.charAt(i)] = i; + } + } + } + } +}; +var DecodeBase64StringError = class extends Error { + constructor() { + super(...arguments); + this.name = "DecodeBase64StringError"; + } +}; +var base64Encode = function(str) { + const utf8Bytes = stringToByteArray$1(str); + return base64.encodeByteArray(utf8Bytes, true); +}; +var base64urlEncodeWithoutPadding = function(str) { + return base64Encode(str).replace(/\./g, ""); +}; +var base64Decode = function(str) { + try { + return base64.decodeString(str, true); + } catch (e) { + console.error("base64Decode failed: ", e); + } + return null; +}; +function deepCopy(value) { + return deepExtend(void 0, value); +} +function deepExtend(target, source) { + if (!(source instanceof Object)) { + return source; + } + switch (source.constructor) { + case Date: + const dateValue = source; + return new Date(dateValue.getTime()); + case Object: + if (target === void 0) { + target = {}; + } + break; + case Array: + target = []; + break; + default: + return source; + } + for (const prop in source) { + if (!source.hasOwnProperty(prop) || !isValidKey(prop)) { + continue; + } + target[prop] = deepExtend(target[prop], source[prop]); + } + return target; +} +function isValidKey(key) { + return key !== "__proto__"; +} +function getGlobal() { + if (typeof self !== "undefined") { + return self; + } + if (typeof window !== "undefined") { + return window; + } + if (typeof global !== "undefined") { + return global; + } + throw new Error("Unable to locate global object."); +} +var getDefaultsFromGlobal = () => getGlobal().__FIREBASE_DEFAULTS__; +var getDefaultsFromEnvVariable = () => { + if (typeof process === "undefined" || typeof process.env === "undefined") { + return; + } + const defaultsJsonString = process.env.__FIREBASE_DEFAULTS__; + if (defaultsJsonString) { + return JSON.parse(defaultsJsonString); + } +}; +var getDefaultsFromCookie = () => { + if (typeof document === "undefined") { + return; + } + let match; + try { + match = document.cookie.match(/__FIREBASE_DEFAULTS__=([^;]+)/); + } catch (e) { + return; + } + const decoded = match && base64Decode(match[1]); + return decoded && JSON.parse(decoded); +}; +var getDefaults = () => { + try { + return getDefaultsFromGlobal() || getDefaultsFromEnvVariable() || getDefaultsFromCookie(); + } catch (e) { + console.info(`Unable to get __FIREBASE_DEFAULTS__ due to: ${e}`); + return; + } +}; +var getDefaultEmulatorHost = (productName) => { + var _a, _b; + return (_b = (_a = getDefaults()) === null || _a === void 0 ? void 0 : _a.emulatorHosts) === null || _b === void 0 ? void 0 : _b[productName]; +}; +var getDefaultEmulatorHostnameAndPort = (productName) => { + const host = getDefaultEmulatorHost(productName); + if (!host) { + return void 0; + } + const separatorIndex = host.lastIndexOf(":"); + if (separatorIndex <= 0 || separatorIndex + 1 === host.length) { + throw new Error(`Invalid host ${host} with no separate hostname and port!`); + } + const port = parseInt(host.substring(separatorIndex + 1), 10); + if (host[0] === "[") { + return [host.substring(1, separatorIndex - 1), port]; + } else { + return [host.substring(0, separatorIndex), port]; + } +}; +var getDefaultAppConfig = () => { + var _a; + return (_a = getDefaults()) === null || _a === void 0 ? void 0 : _a.config; +}; +var getExperimentalSetting = (name4) => { + var _a; + return (_a = getDefaults()) === null || _a === void 0 ? void 0 : _a[`_${name4}`]; +}; +var Deferred = class { + constructor() { + this.reject = () => { + }; + this.resolve = () => { + }; + this.promise = new Promise((resolve, reject) => { + this.resolve = resolve; + this.reject = reject; + }); + } + /** + * Our API internals are not promiseified and cannot because our callback APIs have subtle expectations around + * invoking promises inline, which Promises are forbidden to do. This method accepts an optional node-style callback + * and returns a node-style callback which will resolve or reject the Deferred's promise. + */ + wrapCallback(callback) { + return (error2, value) => { + if (error2) { + this.reject(error2); + } else { + this.resolve(value); + } + if (typeof callback === "function") { + this.promise.catch(() => { + }); + if (callback.length === 1) { + callback(error2); + } else { + callback(error2, value); + } + } + }; + } +}; +function createMockUserToken(token, projectId) { + if (token.uid) { + throw new Error('The "uid" field is no longer supported by mockUserToken. Please use "sub" instead for Firebase Auth User ID.'); + } + const header = { + alg: "none", + type: "JWT" + }; + const project = projectId || "demo-project"; + const iat = token.iat || 0; + const sub = token.sub || token.user_id; + if (!sub) { + throw new Error("mockUserToken must contain 'sub' or 'user_id' field!"); + } + const payload = Object.assign({ + // Set all required fields to decent defaults + iss: `https://securetoken.google.com/${project}`, + aud: project, + iat, + exp: iat + 3600, + auth_time: iat, + sub, + user_id: sub, + firebase: { + sign_in_provider: "custom", + identities: {} + } + }, token); + const signature = ""; + return [ + base64urlEncodeWithoutPadding(JSON.stringify(header)), + base64urlEncodeWithoutPadding(JSON.stringify(payload)), + signature + ].join("."); +} +function getUA() { + if (typeof navigator !== "undefined" && typeof navigator["userAgent"] === "string") { + return navigator["userAgent"]; + } else { + return ""; + } +} +function isMobileCordova() { + return typeof window !== "undefined" && // @ts-ignore Setting up an broadly applicable index signature for Window + // just to deal with this case would probably be a bad idea. + !!(window["cordova"] || window["phonegap"] || window["PhoneGap"]) && /ios|iphone|ipod|ipad|android|blackberry|iemobile/i.test(getUA()); +} +function isBrowserExtension() { + const runtime = typeof chrome === "object" ? chrome.runtime : typeof browser === "object" ? browser.runtime : void 0; + return typeof runtime === "object" && runtime.id !== void 0; +} +function isReactNative() { + return typeof navigator === "object" && navigator["product"] === "ReactNative"; +} +function isIE() { + const ua = getUA(); + return ua.indexOf("MSIE ") >= 0 || ua.indexOf("Trident/") >= 0; +} +function isNodeSdk() { + return CONSTANTS.NODE_CLIENT === true || CONSTANTS.NODE_ADMIN === true; +} +function isIndexedDBAvailable() { + try { + return typeof indexedDB === "object"; + } catch (e) { + return false; + } +} +function validateIndexedDBOpenable() { + return new Promise((resolve, reject) => { + try { + let preExist = true; + const DB_CHECK_NAME = "validate-browser-context-for-indexeddb-analytics-module"; + const request = self.indexedDB.open(DB_CHECK_NAME); + request.onsuccess = () => { + request.result.close(); + if (!preExist) { + self.indexedDB.deleteDatabase(DB_CHECK_NAME); + } + resolve(true); + }; + request.onupgradeneeded = () => { + preExist = false; + }; + request.onerror = () => { + var _a; + reject(((_a = request.error) === null || _a === void 0 ? void 0 : _a.message) || ""); + }; + } catch (error2) { + reject(error2); + } + }); +} +var ERROR_NAME = "FirebaseError"; +var FirebaseError = class _FirebaseError extends Error { + constructor(code, message, customData) { + super(message); + this.code = code; + this.customData = customData; + this.name = ERROR_NAME; + Object.setPrototypeOf(this, _FirebaseError.prototype); + if (Error.captureStackTrace) { + Error.captureStackTrace(this, ErrorFactory.prototype.create); + } + } +}; +var ErrorFactory = class { + constructor(service, serviceName, errors) { + this.service = service; + this.serviceName = serviceName; + this.errors = errors; + } + create(code, ...data) { + const customData = data[0] || {}; + const fullCode = `${this.service}/${code}`; + const template = this.errors[code]; + const message = template ? replaceTemplate(template, customData) : "Error"; + const fullMessage = `${this.serviceName}: ${message} (${fullCode}).`; + const error2 = new FirebaseError(fullCode, fullMessage, customData); + return error2; + } +}; +function replaceTemplate(template, data) { + return template.replace(PATTERN, (_, key) => { + const value = data[key]; + return value != null ? String(value) : `<${key}?>`; + }); +} +var PATTERN = /\{\$([^}]+)}/g; +function jsonEval(str) { + return JSON.parse(str); +} +function stringify(data) { + return JSON.stringify(data); +} +var decode = function(token) { + let header = {}, claims = {}, data = {}, signature = ""; + try { + const parts = token.split("."); + header = jsonEval(base64Decode(parts[0]) || ""); + claims = jsonEval(base64Decode(parts[1]) || ""); + signature = parts[2]; + data = claims["d"] || {}; + delete claims["d"]; + } catch (e) { + } + return { + header, + claims, + data, + signature + }; +}; +var isValidFormat = function(token) { + const decoded = decode(token), claims = decoded.claims; + return !!claims && typeof claims === "object" && claims.hasOwnProperty("iat"); +}; +var isAdmin = function(token) { + const claims = decode(token).claims; + return typeof claims === "object" && claims["admin"] === true; +}; +function contains(obj, key) { + return Object.prototype.hasOwnProperty.call(obj, key); +} +function safeGet(obj, key) { + if (Object.prototype.hasOwnProperty.call(obj, key)) { + return obj[key]; + } else { + return void 0; + } +} +function isEmpty(obj) { + for (const key in obj) { + if (Object.prototype.hasOwnProperty.call(obj, key)) { + return false; + } + } + return true; +} +function map(obj, fn, contextObj) { + const res = {}; + for (const key in obj) { + if (Object.prototype.hasOwnProperty.call(obj, key)) { + res[key] = fn.call(contextObj, obj[key], key, obj); + } + } + return res; +} +function deepEqual(a, b) { + if (a === b) { + return true; + } + const aKeys = Object.keys(a); + const bKeys = Object.keys(b); + for (const k of aKeys) { + if (!bKeys.includes(k)) { + return false; + } + const aProp = a[k]; + const bProp = b[k]; + if (isObject(aProp) && isObject(bProp)) { + if (!deepEqual(aProp, bProp)) { + return false; + } + } else if (aProp !== bProp) { + return false; + } + } + for (const k of bKeys) { + if (!aKeys.includes(k)) { + return false; + } + } + return true; +} +function isObject(thing) { + return thing !== null && typeof thing === "object"; +} +function querystring(querystringParams) { + const params = []; + for (const [key, value] of Object.entries(querystringParams)) { + if (Array.isArray(value)) { + value.forEach((arrayVal) => { + params.push(encodeURIComponent(key) + "=" + encodeURIComponent(arrayVal)); + }); + } else { + params.push(encodeURIComponent(key) + "=" + encodeURIComponent(value)); + } + } + return params.length ? "&" + params.join("&") : ""; +} +function querystringDecode(querystring2) { + const obj = {}; + const tokens = querystring2.replace(/^\?/, "").split("&"); + tokens.forEach((token) => { + if (token) { + const [key, value] = token.split("="); + obj[decodeURIComponent(key)] = decodeURIComponent(value); + } + }); + return obj; +} +function extractQuerystring(url) { + const queryStart = url.indexOf("?"); + if (!queryStart) { + return ""; + } + const fragmentStart = url.indexOf("#", queryStart); + return url.substring(queryStart, fragmentStart > 0 ? fragmentStart : void 0); +} +var Sha1 = class { + constructor() { + this.chain_ = []; + this.buf_ = []; + this.W_ = []; + this.pad_ = []; + this.inbuf_ = 0; + this.total_ = 0; + this.blockSize = 512 / 8; + this.pad_[0] = 128; + for (let i = 1; i < this.blockSize; ++i) { + this.pad_[i] = 0; + } + this.reset(); + } + reset() { + this.chain_[0] = 1732584193; + this.chain_[1] = 4023233417; + this.chain_[2] = 2562383102; + this.chain_[3] = 271733878; + this.chain_[4] = 3285377520; + this.inbuf_ = 0; + this.total_ = 0; + } + /** + * Internal compress helper function. + * @param buf Block to compress. + * @param offset Offset of the block in the buffer. + * @private + */ + compress_(buf, offset) { + if (!offset) { + offset = 0; + } + const W = this.W_; + if (typeof buf === "string") { + for (let i = 0; i < 16; i++) { + W[i] = buf.charCodeAt(offset) << 24 | buf.charCodeAt(offset + 1) << 16 | buf.charCodeAt(offset + 2) << 8 | buf.charCodeAt(offset + 3); + offset += 4; + } + } else { + for (let i = 0; i < 16; i++) { + W[i] = buf[offset] << 24 | buf[offset + 1] << 16 | buf[offset + 2] << 8 | buf[offset + 3]; + offset += 4; + } + } + for (let i = 16; i < 80; i++) { + const t = W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16]; + W[i] = (t << 1 | t >>> 31) & 4294967295; + } + let a = this.chain_[0]; + let b = this.chain_[1]; + let c = this.chain_[2]; + let d = this.chain_[3]; + let e = this.chain_[4]; + let f, k; + for (let i = 0; i < 80; i++) { + if (i < 40) { + if (i < 20) { + f = d ^ b & (c ^ d); + k = 1518500249; + } else { + f = b ^ c ^ d; + k = 1859775393; + } + } else { + if (i < 60) { + f = b & c | d & (b | c); + k = 2400959708; + } else { + f = b ^ c ^ d; + k = 3395469782; + } + } + const t = (a << 5 | a >>> 27) + f + e + k + W[i] & 4294967295; + e = d; + d = c; + c = (b << 30 | b >>> 2) & 4294967295; + b = a; + a = t; + } + this.chain_[0] = this.chain_[0] + a & 4294967295; + this.chain_[1] = this.chain_[1] + b & 4294967295; + this.chain_[2] = this.chain_[2] + c & 4294967295; + this.chain_[3] = this.chain_[3] + d & 4294967295; + this.chain_[4] = this.chain_[4] + e & 4294967295; + } + update(bytes, length) { + if (bytes == null) { + return; + } + if (length === void 0) { + length = bytes.length; + } + const lengthMinusBlock = length - this.blockSize; + let n = 0; + const buf = this.buf_; + let inbuf = this.inbuf_; + while (n < length) { + if (inbuf === 0) { + while (n <= lengthMinusBlock) { + this.compress_(bytes, n); + n += this.blockSize; + } + } + if (typeof bytes === "string") { + while (n < length) { + buf[inbuf] = bytes.charCodeAt(n); + ++inbuf; + ++n; + if (inbuf === this.blockSize) { + this.compress_(buf); + inbuf = 0; + break; + } + } + } else { + while (n < length) { + buf[inbuf] = bytes[n]; + ++inbuf; + ++n; + if (inbuf === this.blockSize) { + this.compress_(buf); + inbuf = 0; + break; + } + } + } + } + this.inbuf_ = inbuf; + this.total_ += length; + } + /** @override */ + digest() { + const digest = []; + let totalBits = this.total_ * 8; + if (this.inbuf_ < 56) { + this.update(this.pad_, 56 - this.inbuf_); + } else { + this.update(this.pad_, this.blockSize - (this.inbuf_ - 56)); + } + for (let i = this.blockSize - 1; i >= 56; i--) { + this.buf_[i] = totalBits & 255; + totalBits /= 256; + } + this.compress_(this.buf_); + let n = 0; + for (let i = 0; i < 5; i++) { + for (let j = 24; j >= 0; j -= 8) { + digest[n] = this.chain_[i] >> j & 255; + ++n; + } + } + return digest; + } +}; +function createSubscribe(executor, onNoObservers) { + const proxy = new ObserverProxy(executor, onNoObservers); + return proxy.subscribe.bind(proxy); +} +var ObserverProxy = class { + /** + * @param executor Function which can make calls to a single Observer + * as a proxy. + * @param onNoObservers Callback when count of Observers goes to zero. + */ + constructor(executor, onNoObservers) { + this.observers = []; + this.unsubscribes = []; + this.observerCount = 0; + this.task = Promise.resolve(); + this.finalized = false; + this.onNoObservers = onNoObservers; + this.task.then(() => { + executor(this); + }).catch((e) => { + this.error(e); + }); + } + next(value) { + this.forEachObserver((observer) => { + observer.next(value); + }); + } + error(error2) { + this.forEachObserver((observer) => { + observer.error(error2); + }); + this.close(error2); + } + complete() { + this.forEachObserver((observer) => { + observer.complete(); + }); + this.close(); + } + /** + * Subscribe function that can be used to add an Observer to the fan-out list. + * + * - We require that no event is sent to a subscriber sychronously to their + * call to subscribe(). + */ + subscribe(nextOrObserver, error2, complete) { + let observer; + if (nextOrObserver === void 0 && error2 === void 0 && complete === void 0) { + throw new Error("Missing Observer."); + } + if (implementsAnyMethods(nextOrObserver, [ + "next", + "error", + "complete" + ])) { + observer = nextOrObserver; + } else { + observer = { + next: nextOrObserver, + error: error2, + complete + }; + } + if (observer.next === void 0) { + observer.next = noop; + } + if (observer.error === void 0) { + observer.error = noop; + } + if (observer.complete === void 0) { + observer.complete = noop; + } + const unsub = this.unsubscribeOne.bind(this, this.observers.length); + if (this.finalized) { + this.task.then(() => { + try { + if (this.finalError) { + observer.error(this.finalError); + } else { + observer.complete(); + } + } catch (e) { + } + return; + }); + } + this.observers.push(observer); + return unsub; + } + // Unsubscribe is synchronous - we guarantee that no events are sent to + // any unsubscribed Observer. + unsubscribeOne(i) { + if (this.observers === void 0 || this.observers[i] === void 0) { + return; + } + delete this.observers[i]; + this.observerCount -= 1; + if (this.observerCount === 0 && this.onNoObservers !== void 0) { + this.onNoObservers(this); + } + } + forEachObserver(fn) { + if (this.finalized) { + return; + } + for (let i = 0; i < this.observers.length; i++) { + this.sendOne(i, fn); + } + } + // Call the Observer via one of it's callback function. We are careful to + // confirm that the observe has not been unsubscribed since this asynchronous + // function had been queued. + sendOne(i, fn) { + this.task.then(() => { + if (this.observers !== void 0 && this.observers[i] !== void 0) { + try { + fn(this.observers[i]); + } catch (e) { + if (typeof console !== "undefined" && console.error) { + console.error(e); + } + } + } + }); + } + close(err) { + if (this.finalized) { + return; + } + this.finalized = true; + if (err !== void 0) { + this.finalError = err; + } + this.task.then(() => { + this.observers = void 0; + this.onNoObservers = void 0; + }); + } +}; +function implementsAnyMethods(obj, methods) { + if (typeof obj !== "object" || obj === null) { + return false; + } + for (const method of methods) { + if (method in obj && typeof obj[method] === "function") { + return true; + } + } + return false; +} +function noop() { +} +function errorPrefix(fnName, argName) { + return `${fnName} failed: ${argName} argument `; +} +var stringToByteArray = function(str) { + const out = []; + let p = 0; + for (let i = 0; i < str.length; i++) { + let c = str.charCodeAt(i); + if (c >= 55296 && c <= 56319) { + const high = c - 55296; + i++; + assert(i < str.length, "Surrogate pair missing trail surrogate."); + const low = str.charCodeAt(i) - 56320; + c = 65536 + (high << 10) + low; + } + if (c < 128) { + out[p++] = c; + } else if (c < 2048) { + out[p++] = c >> 6 | 192; + out[p++] = c & 63 | 128; + } else if (c < 65536) { + out[p++] = c >> 12 | 224; + out[p++] = c >> 6 & 63 | 128; + out[p++] = c & 63 | 128; + } else { + out[p++] = c >> 18 | 240; + out[p++] = c >> 12 & 63 | 128; + out[p++] = c >> 6 & 63 | 128; + out[p++] = c & 63 | 128; + } + } + return out; +}; +var stringLength = function(str) { + let p = 0; + for (let i = 0; i < str.length; i++) { + const c = str.charCodeAt(i); + if (c < 128) { + p++; + } else if (c < 2048) { + p += 2; + } else if (c >= 55296 && c <= 56319) { + p += 4; + i++; + } else { + p += 3; + } + } + return p; +}; +var MAX_VALUE_MILLIS = 4 * 60 * 60 * 1e3; +function getModularInstance(service) { + if (service && service._delegate) { + return service._delegate; + } else { + return service; + } +} + +// node_modules/.pnpm/@firebase+component@0.6.4/node_modules/@firebase/component/dist/esm/index.esm2017.js +var Component = class { + /** + * + * @param name The public service name, e.g. app, auth, firestore, database + * @param instanceFactory Service factory responsible for creating the public interface + * @param type whether the service provided by the component is public or private + */ + constructor(name4, instanceFactory, type) { + this.name = name4; + this.instanceFactory = instanceFactory; + this.type = type; + this.multipleInstances = false; + this.serviceProps = {}; + this.instantiationMode = "LAZY"; + this.onInstanceCreated = null; + } + setInstantiationMode(mode) { + this.instantiationMode = mode; + return this; + } + setMultipleInstances(multipleInstances) { + this.multipleInstances = multipleInstances; + return this; + } + setServiceProps(props) { + this.serviceProps = props; + return this; + } + setInstanceCreatedCallback(callback) { + this.onInstanceCreated = callback; + return this; + } +}; +var DEFAULT_ENTRY_NAME = "[DEFAULT]"; +var Provider = class { + constructor(name4, container) { + this.name = name4; + this.container = container; + this.component = null; + this.instances = /* @__PURE__ */ new Map(); + this.instancesDeferred = /* @__PURE__ */ new Map(); + this.instancesOptions = /* @__PURE__ */ new Map(); + this.onInitCallbacks = /* @__PURE__ */ new Map(); + } + /** + * @param identifier A provider can provide mulitple instances of a service + * if this.component.multipleInstances is true. + */ + get(identifier) { + const normalizedIdentifier = this.normalizeInstanceIdentifier(identifier); + if (!this.instancesDeferred.has(normalizedIdentifier)) { + const deferred = new Deferred(); + this.instancesDeferred.set(normalizedIdentifier, deferred); + if (this.isInitialized(normalizedIdentifier) || this.shouldAutoInitialize()) { + try { + const instance = this.getOrInitializeService({ + instanceIdentifier: normalizedIdentifier + }); + if (instance) { + deferred.resolve(instance); + } + } catch (e) { + } + } + } + return this.instancesDeferred.get(normalizedIdentifier).promise; + } + getImmediate(options) { + var _a; + const normalizedIdentifier = this.normalizeInstanceIdentifier(options === null || options === void 0 ? void 0 : options.identifier); + const optional = (_a = options === null || options === void 0 ? void 0 : options.optional) !== null && _a !== void 0 ? _a : false; + if (this.isInitialized(normalizedIdentifier) || this.shouldAutoInitialize()) { + try { + return this.getOrInitializeService({ + instanceIdentifier: normalizedIdentifier + }); + } catch (e) { + if (optional) { + return null; + } else { + throw e; + } + } + } else { + if (optional) { + return null; + } else { + throw Error(`Service ${this.name} is not available`); + } + } + } + getComponent() { + return this.component; + } + setComponent(component) { + if (component.name !== this.name) { + throw Error(`Mismatching Component ${component.name} for Provider ${this.name}.`); + } + if (this.component) { + throw Error(`Component for ${this.name} has already been provided`); + } + this.component = component; + if (!this.shouldAutoInitialize()) { + return; + } + if (isComponentEager(component)) { + try { + this.getOrInitializeService({ instanceIdentifier: DEFAULT_ENTRY_NAME }); + } catch (e) { + } + } + for (const [instanceIdentifier, instanceDeferred] of this.instancesDeferred.entries()) { + const normalizedIdentifier = this.normalizeInstanceIdentifier(instanceIdentifier); + try { + const instance = this.getOrInitializeService({ + instanceIdentifier: normalizedIdentifier + }); + instanceDeferred.resolve(instance); + } catch (e) { + } + } + } + clearInstance(identifier = DEFAULT_ENTRY_NAME) { + this.instancesDeferred.delete(identifier); + this.instancesOptions.delete(identifier); + this.instances.delete(identifier); + } + // app.delete() will call this method on every provider to delete the services + // TODO: should we mark the provider as deleted? + async delete() { + const services = Array.from(this.instances.values()); + await Promise.all([ + ...services.filter((service) => "INTERNAL" in service).map((service) => service.INTERNAL.delete()), + ...services.filter((service) => "_delete" in service).map((service) => service._delete()) + ]); + } + isComponentSet() { + return this.component != null; + } + isInitialized(identifier = DEFAULT_ENTRY_NAME) { + return this.instances.has(identifier); + } + getOptions(identifier = DEFAULT_ENTRY_NAME) { + return this.instancesOptions.get(identifier) || {}; + } + initialize(opts = {}) { + const { options = {} } = opts; + const normalizedIdentifier = this.normalizeInstanceIdentifier(opts.instanceIdentifier); + if (this.isInitialized(normalizedIdentifier)) { + throw Error(`${this.name}(${normalizedIdentifier}) has already been initialized`); + } + if (!this.isComponentSet()) { + throw Error(`Component ${this.name} has not been registered yet`); + } + const instance = this.getOrInitializeService({ + instanceIdentifier: normalizedIdentifier, + options + }); + for (const [instanceIdentifier, instanceDeferred] of this.instancesDeferred.entries()) { + const normalizedDeferredIdentifier = this.normalizeInstanceIdentifier(instanceIdentifier); + if (normalizedIdentifier === normalizedDeferredIdentifier) { + instanceDeferred.resolve(instance); + } + } + return instance; + } + /** + * + * @param callback - a function that will be invoked after the provider has been initialized by calling provider.initialize(). + * The function is invoked SYNCHRONOUSLY, so it should not execute any longrunning tasks in order to not block the program. + * + * @param identifier An optional instance identifier + * @returns a function to unregister the callback + */ + onInit(callback, identifier) { + var _a; + const normalizedIdentifier = this.normalizeInstanceIdentifier(identifier); + const existingCallbacks = (_a = this.onInitCallbacks.get(normalizedIdentifier)) !== null && _a !== void 0 ? _a : /* @__PURE__ */ new Set(); + existingCallbacks.add(callback); + this.onInitCallbacks.set(normalizedIdentifier, existingCallbacks); + const existingInstance = this.instances.get(normalizedIdentifier); + if (existingInstance) { + callback(existingInstance, normalizedIdentifier); + } + return () => { + existingCallbacks.delete(callback); + }; + } + /** + * Invoke onInit callbacks synchronously + * @param instance the service instance` + */ + invokeOnInitCallbacks(instance, identifier) { + const callbacks = this.onInitCallbacks.get(identifier); + if (!callbacks) { + return; + } + for (const callback of callbacks) { + try { + callback(instance, identifier); + } catch (_a) { + } + } + } + getOrInitializeService({ instanceIdentifier, options = {} }) { + let instance = this.instances.get(instanceIdentifier); + if (!instance && this.component) { + instance = this.component.instanceFactory(this.container, { + instanceIdentifier: normalizeIdentifierForFactory(instanceIdentifier), + options + }); + this.instances.set(instanceIdentifier, instance); + this.instancesOptions.set(instanceIdentifier, options); + this.invokeOnInitCallbacks(instance, instanceIdentifier); + if (this.component.onInstanceCreated) { + try { + this.component.onInstanceCreated(this.container, instanceIdentifier, instance); + } catch (_a) { + } + } + } + return instance || null; + } + normalizeInstanceIdentifier(identifier = DEFAULT_ENTRY_NAME) { + if (this.component) { + return this.component.multipleInstances ? identifier : DEFAULT_ENTRY_NAME; + } else { + return identifier; + } + } + shouldAutoInitialize() { + return !!this.component && this.component.instantiationMode !== "EXPLICIT"; + } +}; +function normalizeIdentifierForFactory(identifier) { + return identifier === DEFAULT_ENTRY_NAME ? void 0 : identifier; +} +function isComponentEager(component) { + return component.instantiationMode === "EAGER"; +} +var ComponentContainer = class { + constructor(name4) { + this.name = name4; + this.providers = /* @__PURE__ */ new Map(); + } + /** + * + * @param component Component being added + * @param overwrite When a component with the same name has already been registered, + * if overwrite is true: overwrite the existing component with the new component and create a new + * provider with the new component. It can be useful in tests where you want to use different mocks + * for different tests. + * if overwrite is false: throw an exception + */ + addComponent(component) { + const provider = this.getProvider(component.name); + if (provider.isComponentSet()) { + throw new Error(`Component ${component.name} has already been registered with ${this.name}`); + } + provider.setComponent(component); + } + addOrOverwriteComponent(component) { + const provider = this.getProvider(component.name); + if (provider.isComponentSet()) { + this.providers.delete(component.name); + } + this.addComponent(component); + } + /** + * getProvider provides a type safe interface where it can only be called with a field name + * present in NameServiceMapping interface. + * + * Firebase SDKs providing services should extend NameServiceMapping interface to register + * themselves. + */ + getProvider(name4) { + if (this.providers.has(name4)) { + return this.providers.get(name4); + } + const provider = new Provider(name4, this); + this.providers.set(name4, provider); + return provider; + } + getProviders() { + return Array.from(this.providers.values()); + } +}; + +// node_modules/.pnpm/@firebase+logger@0.4.0/node_modules/@firebase/logger/dist/esm/index.esm2017.js +var instances = []; +var LogLevel; +(function(LogLevel2) { + LogLevel2[LogLevel2["DEBUG"] = 0] = "DEBUG"; + LogLevel2[LogLevel2["VERBOSE"] = 1] = "VERBOSE"; + LogLevel2[LogLevel2["INFO"] = 2] = "INFO"; + LogLevel2[LogLevel2["WARN"] = 3] = "WARN"; + LogLevel2[LogLevel2["ERROR"] = 4] = "ERROR"; + LogLevel2[LogLevel2["SILENT"] = 5] = "SILENT"; +})(LogLevel || (LogLevel = {})); +var levelStringToEnum = { + "debug": LogLevel.DEBUG, + "verbose": LogLevel.VERBOSE, + "info": LogLevel.INFO, + "warn": LogLevel.WARN, + "error": LogLevel.ERROR, + "silent": LogLevel.SILENT +}; +var defaultLogLevel = LogLevel.INFO; +var ConsoleMethod = { + [LogLevel.DEBUG]: "log", + [LogLevel.VERBOSE]: "log", + [LogLevel.INFO]: "info", + [LogLevel.WARN]: "warn", + [LogLevel.ERROR]: "error" +}; +var defaultLogHandler = (instance, logType, ...args) => { + if (logType < instance.logLevel) { + return; + } + const now = (/* @__PURE__ */ new Date()).toISOString(); + const method = ConsoleMethod[logType]; + if (method) { + console[method](`[${now}] ${instance.name}:`, ...args); + } else { + throw new Error(`Attempted to log a message with an invalid logType (value: ${logType})`); + } +}; +var Logger = class { + /** + * Gives you an instance of a Logger to capture messages according to + * Firebase's logging scheme. + * + * @param name The name that the logs will be associated with + */ + constructor(name4) { + this.name = name4; + this._logLevel = defaultLogLevel; + this._logHandler = defaultLogHandler; + this._userLogHandler = null; + instances.push(this); + } + get logLevel() { + return this._logLevel; + } + set logLevel(val) { + if (!(val in LogLevel)) { + throw new TypeError(`Invalid value "${val}" assigned to \`logLevel\``); + } + this._logLevel = val; + } + // Workaround for setter/getter having to be the same type. + setLogLevel(val) { + this._logLevel = typeof val === "string" ? levelStringToEnum[val] : val; + } + get logHandler() { + return this._logHandler; + } + set logHandler(val) { + if (typeof val !== "function") { + throw new TypeError("Value assigned to `logHandler` must be a function"); + } + this._logHandler = val; + } + get userLogHandler() { + return this._userLogHandler; + } + set userLogHandler(val) { + this._userLogHandler = val; + } + /** + * The functions below are all based on the `console` interface + */ + debug(...args) { + this._userLogHandler && this._userLogHandler(this, LogLevel.DEBUG, ...args); + this._logHandler(this, LogLevel.DEBUG, ...args); + } + log(...args) { + this._userLogHandler && this._userLogHandler(this, LogLevel.VERBOSE, ...args); + this._logHandler(this, LogLevel.VERBOSE, ...args); + } + info(...args) { + this._userLogHandler && this._userLogHandler(this, LogLevel.INFO, ...args); + this._logHandler(this, LogLevel.INFO, ...args); + } + warn(...args) { + this._userLogHandler && this._userLogHandler(this, LogLevel.WARN, ...args); + this._logHandler(this, LogLevel.WARN, ...args); + } + error(...args) { + this._userLogHandler && this._userLogHandler(this, LogLevel.ERROR, ...args); + this._logHandler(this, LogLevel.ERROR, ...args); + } +}; + +// node_modules/.pnpm/idb@7.1.1/node_modules/idb/build/wrap-idb-value.js +var instanceOfAny = (object, constructors) => constructors.some((c) => object instanceof c); +var idbProxyableTypes; +var cursorAdvanceMethods; +function getIdbProxyableTypes() { + return idbProxyableTypes || (idbProxyableTypes = [ + IDBDatabase, + IDBObjectStore, + IDBIndex, + IDBCursor, + IDBTransaction + ]); +} +function getCursorAdvanceMethods() { + return cursorAdvanceMethods || (cursorAdvanceMethods = [ + IDBCursor.prototype.advance, + IDBCursor.prototype.continue, + IDBCursor.prototype.continuePrimaryKey + ]); +} +var cursorRequestMap = /* @__PURE__ */ new WeakMap(); +var transactionDoneMap = /* @__PURE__ */ new WeakMap(); +var transactionStoreNamesMap = /* @__PURE__ */ new WeakMap(); +var transformCache = /* @__PURE__ */ new WeakMap(); +var reverseTransformCache = /* @__PURE__ */ new WeakMap(); +function promisifyRequest(request) { + const promise = new Promise((resolve, reject) => { + const unlisten = () => { + request.removeEventListener("success", success); + request.removeEventListener("error", error2); + }; + const success = () => { + resolve(wrap(request.result)); + unlisten(); + }; + const error2 = () => { + reject(request.error); + unlisten(); + }; + request.addEventListener("success", success); + request.addEventListener("error", error2); + }); + promise.then((value) => { + if (value instanceof IDBCursor) { + cursorRequestMap.set(value, request); + } + }).catch(() => { + }); + reverseTransformCache.set(promise, request); + return promise; +} +function cacheDonePromiseForTransaction(tx) { + if (transactionDoneMap.has(tx)) + return; + const done = new Promise((resolve, reject) => { + const unlisten = () => { + tx.removeEventListener("complete", complete); + tx.removeEventListener("error", error2); + tx.removeEventListener("abort", error2); + }; + const complete = () => { + resolve(); + unlisten(); + }; + const error2 = () => { + reject(tx.error || new DOMException("AbortError", "AbortError")); + unlisten(); + }; + tx.addEventListener("complete", complete); + tx.addEventListener("error", error2); + tx.addEventListener("abort", error2); + }); + transactionDoneMap.set(tx, done); +} +var idbProxyTraps = { + get(target, prop, receiver) { + if (target instanceof IDBTransaction) { + if (prop === "done") + return transactionDoneMap.get(target); + if (prop === "objectStoreNames") { + return target.objectStoreNames || transactionStoreNamesMap.get(target); + } + if (prop === "store") { + return receiver.objectStoreNames[1] ? void 0 : receiver.objectStore(receiver.objectStoreNames[0]); + } + } + return wrap(target[prop]); + }, + set(target, prop, value) { + target[prop] = value; + return true; + }, + has(target, prop) { + if (target instanceof IDBTransaction && (prop === "done" || prop === "store")) { + return true; + } + return prop in target; + } +}; +function replaceTraps(callback) { + idbProxyTraps = callback(idbProxyTraps); +} +function wrapFunction(func) { + if (func === IDBDatabase.prototype.transaction && !("objectStoreNames" in IDBTransaction.prototype)) { + return function(storeNames, ...args) { + const tx = func.call(unwrap(this), storeNames, ...args); + transactionStoreNamesMap.set(tx, storeNames.sort ? storeNames.sort() : [storeNames]); + return wrap(tx); + }; + } + if (getCursorAdvanceMethods().includes(func)) { + return function(...args) { + func.apply(unwrap(this), args); + return wrap(cursorRequestMap.get(this)); + }; + } + return function(...args) { + return wrap(func.apply(unwrap(this), args)); + }; +} +function transformCachableValue(value) { + if (typeof value === "function") + return wrapFunction(value); + if (value instanceof IDBTransaction) + cacheDonePromiseForTransaction(value); + if (instanceOfAny(value, getIdbProxyableTypes())) + return new Proxy(value, idbProxyTraps); + return value; +} +function wrap(value) { + if (value instanceof IDBRequest) + return promisifyRequest(value); + if (transformCache.has(value)) + return transformCache.get(value); + const newValue = transformCachableValue(value); + if (newValue !== value) { + transformCache.set(value, newValue); + reverseTransformCache.set(newValue, value); + } + return newValue; +} +var unwrap = (value) => reverseTransformCache.get(value); + +// node_modules/.pnpm/idb@7.1.1/node_modules/idb/build/index.js +function openDB(name4, version4, { blocked, upgrade, blocking, terminated } = {}) { + const request = indexedDB.open(name4, version4); + const openPromise = wrap(request); + if (upgrade) { + request.addEventListener("upgradeneeded", (event) => { + upgrade(wrap(request.result), event.oldVersion, event.newVersion, wrap(request.transaction), event); + }); + } + if (blocked) { + request.addEventListener("blocked", (event) => blocked( + // Casting due to https://github.com/microsoft/TypeScript-DOM-lib-generator/pull/1405 + event.oldVersion, + event.newVersion, + event + )); + } + openPromise.then((db) => { + if (terminated) + db.addEventListener("close", () => terminated()); + if (blocking) { + db.addEventListener("versionchange", (event) => blocking(event.oldVersion, event.newVersion, event)); + } + }).catch(() => { + }); + return openPromise; +} +var readMethods = ["get", "getKey", "getAll", "getAllKeys", "count"]; +var writeMethods = ["put", "add", "delete", "clear"]; +var cachedMethods = /* @__PURE__ */ new Map(); +function getMethod(target, prop) { + if (!(target instanceof IDBDatabase && !(prop in target) && typeof prop === "string")) { + return; + } + if (cachedMethods.get(prop)) + return cachedMethods.get(prop); + const targetFuncName = prop.replace(/FromIndex$/, ""); + const useIndex = prop !== targetFuncName; + const isWrite = writeMethods.includes(targetFuncName); + if ( + // Bail if the target doesn't exist on the target. Eg, getAll isn't in Edge. + !(targetFuncName in (useIndex ? IDBIndex : IDBObjectStore).prototype) || !(isWrite || readMethods.includes(targetFuncName)) + ) { + return; + } + const method = async function(storeName, ...args) { + const tx = this.transaction(storeName, isWrite ? "readwrite" : "readonly"); + let target2 = tx.store; + if (useIndex) + target2 = target2.index(args.shift()); + return (await Promise.all([ + target2[targetFuncName](...args), + isWrite && tx.done + ]))[0]; + }; + cachedMethods.set(prop, method); + return method; +} +replaceTraps((oldTraps) => ({ + ...oldTraps, + get: (target, prop, receiver) => getMethod(target, prop) || oldTraps.get(target, prop, receiver), + has: (target, prop) => !!getMethod(target, prop) || oldTraps.has(target, prop) +})); + +// node_modules/.pnpm/@firebase+app@0.9.15/node_modules/@firebase/app/dist/esm/index.esm2017.js +var PlatformLoggerServiceImpl = class { + constructor(container) { + this.container = container; + } + // In initial implementation, this will be called by installations on + // auth token refresh, and installations will send this string. + getPlatformInfoString() { + const providers = this.container.getProviders(); + return providers.map((provider) => { + if (isVersionServiceProvider(provider)) { + const service = provider.getImmediate(); + return `${service.library}/${service.version}`; + } else { + return null; + } + }).filter((logString) => logString).join(" "); + } +}; +function isVersionServiceProvider(provider) { + const component = provider.getComponent(); + return (component === null || component === void 0 ? void 0 : component.type) === "VERSION"; +} +var name$o = "@firebase/app"; +var version$1 = "0.9.15"; +var logger = new Logger("@firebase/app"); +var name$n = "@firebase/app-compat"; +var name$m = "@firebase/analytics-compat"; +var name$l = "@firebase/analytics"; +var name$k = "@firebase/app-check-compat"; +var name$j = "@firebase/app-check"; +var name$i = "@firebase/auth"; +var name$h = "@firebase/auth-compat"; +var name$g = "@firebase/database"; +var name$f = "@firebase/database-compat"; +var name$e = "@firebase/functions"; +var name$d = "@firebase/functions-compat"; +var name$c = "@firebase/installations"; +var name$b = "@firebase/installations-compat"; +var name$a = "@firebase/messaging"; +var name$9 = "@firebase/messaging-compat"; +var name$8 = "@firebase/performance"; +var name$7 = "@firebase/performance-compat"; +var name$6 = "@firebase/remote-config"; +var name$5 = "@firebase/remote-config-compat"; +var name$4 = "@firebase/storage"; +var name$3 = "@firebase/storage-compat"; +var name$2 = "@firebase/firestore"; +var name$1 = "@firebase/firestore-compat"; +var name = "firebase"; +var version = "10.1.0"; +var DEFAULT_ENTRY_NAME2 = "[DEFAULT]"; +var PLATFORM_LOG_STRING = { + [name$o]: "fire-core", + [name$n]: "fire-core-compat", + [name$l]: "fire-analytics", + [name$m]: "fire-analytics-compat", + [name$j]: "fire-app-check", + [name$k]: "fire-app-check-compat", + [name$i]: "fire-auth", + [name$h]: "fire-auth-compat", + [name$g]: "fire-rtdb", + [name$f]: "fire-rtdb-compat", + [name$e]: "fire-fn", + [name$d]: "fire-fn-compat", + [name$c]: "fire-iid", + [name$b]: "fire-iid-compat", + [name$a]: "fire-fcm", + [name$9]: "fire-fcm-compat", + [name$8]: "fire-perf", + [name$7]: "fire-perf-compat", + [name$6]: "fire-rc", + [name$5]: "fire-rc-compat", + [name$4]: "fire-gcs", + [name$3]: "fire-gcs-compat", + [name$2]: "fire-fst", + [name$1]: "fire-fst-compat", + "fire-js": "fire-js", + [name]: "fire-js-all" +}; +var _apps = /* @__PURE__ */ new Map(); +var _components = /* @__PURE__ */ new Map(); +function _addComponent(app, component) { + try { + app.container.addComponent(component); + } catch (e) { + logger.debug(`Component ${component.name} failed to register with FirebaseApp ${app.name}`, e); + } +} +function _registerComponent(component) { + const componentName = component.name; + if (_components.has(componentName)) { + logger.debug(`There were multiple attempts to register component ${componentName}.`); + return false; + } + _components.set(componentName, component); + for (const app of _apps.values()) { + _addComponent(app, component); + } + return true; +} +function _getProvider(app, name4) { + const heartbeatController = app.container.getProvider("heartbeat").getImmediate({ optional: true }); + if (heartbeatController) { + void heartbeatController.triggerHeartbeat(); + } + return app.container.getProvider(name4); +} +var ERRORS = { + [ + "no-app" + /* AppError.NO_APP */ + ]: "No Firebase App '{$appName}' has been created - call initializeApp() first", + [ + "bad-app-name" + /* AppError.BAD_APP_NAME */ + ]: "Illegal App name: '{$appName}", + [ + "duplicate-app" + /* AppError.DUPLICATE_APP */ + ]: "Firebase App named '{$appName}' already exists with different options or config", + [ + "app-deleted" + /* AppError.APP_DELETED */ + ]: "Firebase App named '{$appName}' already deleted", + [ + "no-options" + /* AppError.NO_OPTIONS */ + ]: "Need to provide options, when not being deployed to hosting via source.", + [ + "invalid-app-argument" + /* AppError.INVALID_APP_ARGUMENT */ + ]: "firebase.{$appName}() takes either no argument or a Firebase App instance.", + [ + "invalid-log-argument" + /* AppError.INVALID_LOG_ARGUMENT */ + ]: "First argument to `onLog` must be null or a function.", + [ + "idb-open" + /* AppError.IDB_OPEN */ + ]: "Error thrown when opening IndexedDB. Original error: {$originalErrorMessage}.", + [ + "idb-get" + /* AppError.IDB_GET */ + ]: "Error thrown when reading from IndexedDB. Original error: {$originalErrorMessage}.", + [ + "idb-set" + /* AppError.IDB_WRITE */ + ]: "Error thrown when writing to IndexedDB. Original error: {$originalErrorMessage}.", + [ + "idb-delete" + /* AppError.IDB_DELETE */ + ]: "Error thrown when deleting from IndexedDB. Original error: {$originalErrorMessage}." +}; +var ERROR_FACTORY = new ErrorFactory("app", "Firebase", ERRORS); +var FirebaseAppImpl = class { + constructor(options, config, container) { + this._isDeleted = false; + this._options = Object.assign({}, options); + this._config = Object.assign({}, config); + this._name = config.name; + this._automaticDataCollectionEnabled = config.automaticDataCollectionEnabled; + this._container = container; + this.container.addComponent(new Component( + "app", + () => this, + "PUBLIC" + /* ComponentType.PUBLIC */ + )); + } + get automaticDataCollectionEnabled() { + this.checkDestroyed(); + return this._automaticDataCollectionEnabled; + } + set automaticDataCollectionEnabled(val) { + this.checkDestroyed(); + this._automaticDataCollectionEnabled = val; + } + get name() { + this.checkDestroyed(); + return this._name; + } + get options() { + this.checkDestroyed(); + return this._options; + } + get config() { + this.checkDestroyed(); + return this._config; + } + get container() { + return this._container; + } + get isDeleted() { + return this._isDeleted; + } + set isDeleted(val) { + this._isDeleted = val; + } + /** + * This function will throw an Error if the App has already been deleted - + * use before performing API actions on the App. + */ + checkDestroyed() { + if (this.isDeleted) { + throw ERROR_FACTORY.create("app-deleted", { appName: this._name }); + } + } +}; +var SDK_VERSION = version; +function initializeApp(_options, rawConfig = {}) { + let options = _options; + if (typeof rawConfig !== "object") { + const name5 = rawConfig; + rawConfig = { name: name5 }; + } + const config = Object.assign({ name: DEFAULT_ENTRY_NAME2, automaticDataCollectionEnabled: false }, rawConfig); + const name4 = config.name; + if (typeof name4 !== "string" || !name4) { + throw ERROR_FACTORY.create("bad-app-name", { + appName: String(name4) + }); + } + options || (options = getDefaultAppConfig()); + if (!options) { + throw ERROR_FACTORY.create( + "no-options" + /* AppError.NO_OPTIONS */ + ); + } + const existingApp = _apps.get(name4); + if (existingApp) { + if (deepEqual(options, existingApp.options) && deepEqual(config, existingApp.config)) { + return existingApp; + } else { + throw ERROR_FACTORY.create("duplicate-app", { appName: name4 }); + } + } + const container = new ComponentContainer(name4); + for (const component of _components.values()) { + container.addComponent(component); + } + const newApp = new FirebaseAppImpl(options, config, container); + _apps.set(name4, newApp); + return newApp; +} +function getApp(name4 = DEFAULT_ENTRY_NAME2) { + const app = _apps.get(name4); + if (!app && name4 === DEFAULT_ENTRY_NAME2 && getDefaultAppConfig()) { + return initializeApp(); + } + if (!app) { + throw ERROR_FACTORY.create("no-app", { appName: name4 }); + } + return app; +} +function registerVersion(libraryKeyOrName, version4, variant) { + var _a; + let library = (_a = PLATFORM_LOG_STRING[libraryKeyOrName]) !== null && _a !== void 0 ? _a : libraryKeyOrName; + if (variant) { + library += `-${variant}`; + } + const libraryMismatch = library.match(/\s|\//); + const versionMismatch = version4.match(/\s|\//); + if (libraryMismatch || versionMismatch) { + const warning = [ + `Unable to register library "${library}" with version "${version4}":` + ]; + if (libraryMismatch) { + warning.push(`library name "${library}" contains illegal characters (whitespace or "/")`); + } + if (libraryMismatch && versionMismatch) { + warning.push("and"); + } + if (versionMismatch) { + warning.push(`version name "${version4}" contains illegal characters (whitespace or "/")`); + } + logger.warn(warning.join(" ")); + return; + } + _registerComponent(new Component( + `${library}-version`, + () => ({ library, version: version4 }), + "VERSION" + /* ComponentType.VERSION */ + )); +} +var DB_NAME = "firebase-heartbeat-database"; +var DB_VERSION = 1; +var STORE_NAME = "firebase-heartbeat-store"; +var dbPromise = null; +function getDbPromise() { + if (!dbPromise) { + dbPromise = openDB(DB_NAME, DB_VERSION, { + upgrade: (db, oldVersion) => { + switch (oldVersion) { + case 0: + db.createObjectStore(STORE_NAME); + } + } + }).catch((e) => { + throw ERROR_FACTORY.create("idb-open", { + originalErrorMessage: e.message + }); + }); + } + return dbPromise; +} +async function readHeartbeatsFromIndexedDB(app) { + try { + const db = await getDbPromise(); + const result = await db.transaction(STORE_NAME).objectStore(STORE_NAME).get(computeKey(app)); + return result; + } catch (e) { + if (e instanceof FirebaseError) { + logger.warn(e.message); + } else { + const idbGetError = ERROR_FACTORY.create("idb-get", { + originalErrorMessage: e === null || e === void 0 ? void 0 : e.message + }); + logger.warn(idbGetError.message); + } + } +} +async function writeHeartbeatsToIndexedDB(app, heartbeatObject) { + try { + const db = await getDbPromise(); + const tx = db.transaction(STORE_NAME, "readwrite"); + const objectStore = tx.objectStore(STORE_NAME); + await objectStore.put(heartbeatObject, computeKey(app)); + await tx.done; + } catch (e) { + if (e instanceof FirebaseError) { + logger.warn(e.message); + } else { + const idbGetError = ERROR_FACTORY.create("idb-set", { + originalErrorMessage: e === null || e === void 0 ? void 0 : e.message + }); + logger.warn(idbGetError.message); + } + } +} +function computeKey(app) { + return `${app.name}!${app.options.appId}`; +} +var MAX_HEADER_BYTES = 1024; +var STORED_HEARTBEAT_RETENTION_MAX_MILLIS = 30 * 24 * 60 * 60 * 1e3; +var HeartbeatServiceImpl = class { + constructor(container) { + this.container = container; + this._heartbeatsCache = null; + const app = this.container.getProvider("app").getImmediate(); + this._storage = new HeartbeatStorageImpl(app); + this._heartbeatsCachePromise = this._storage.read().then((result) => { + this._heartbeatsCache = result; + return result; + }); + } + /** + * Called to report a heartbeat. The function will generate + * a HeartbeatsByUserAgent object, update heartbeatsCache, and persist it + * to IndexedDB. + * Note that we only store one heartbeat per day. So if a heartbeat for today is + * already logged, subsequent calls to this function in the same day will be ignored. + */ + async triggerHeartbeat() { + const platformLogger = this.container.getProvider("platform-logger").getImmediate(); + const agent = platformLogger.getPlatformInfoString(); + const date = getUTCDateString(); + if (this._heartbeatsCache === null) { + this._heartbeatsCache = await this._heartbeatsCachePromise; + } + if (this._heartbeatsCache.lastSentHeartbeatDate === date || this._heartbeatsCache.heartbeats.some((singleDateHeartbeat) => singleDateHeartbeat.date === date)) { + return; + } else { + this._heartbeatsCache.heartbeats.push({ date, agent }); + } + this._heartbeatsCache.heartbeats = this._heartbeatsCache.heartbeats.filter((singleDateHeartbeat) => { + const hbTimestamp = new Date(singleDateHeartbeat.date).valueOf(); + const now = Date.now(); + return now - hbTimestamp <= STORED_HEARTBEAT_RETENTION_MAX_MILLIS; + }); + return this._storage.overwrite(this._heartbeatsCache); + } + /** + * Returns a base64 encoded string which can be attached to the heartbeat-specific header directly. + * It also clears all heartbeats from memory as well as in IndexedDB. + * + * NOTE: Consuming product SDKs should not send the header if this method + * returns an empty string. + */ + async getHeartbeatsHeader() { + if (this._heartbeatsCache === null) { + await this._heartbeatsCachePromise; + } + if (this._heartbeatsCache === null || this._heartbeatsCache.heartbeats.length === 0) { + return ""; + } + const date = getUTCDateString(); + const { heartbeatsToSend, unsentEntries } = extractHeartbeatsForHeader(this._heartbeatsCache.heartbeats); + const headerString = base64urlEncodeWithoutPadding(JSON.stringify({ version: 2, heartbeats: heartbeatsToSend })); + this._heartbeatsCache.lastSentHeartbeatDate = date; + if (unsentEntries.length > 0) { + this._heartbeatsCache.heartbeats = unsentEntries; + await this._storage.overwrite(this._heartbeatsCache); + } else { + this._heartbeatsCache.heartbeats = []; + void this._storage.overwrite(this._heartbeatsCache); + } + return headerString; + } +}; +function getUTCDateString() { + const today = /* @__PURE__ */ new Date(); + return today.toISOString().substring(0, 10); +} +function extractHeartbeatsForHeader(heartbeatsCache, maxSize = MAX_HEADER_BYTES) { + const heartbeatsToSend = []; + let unsentEntries = heartbeatsCache.slice(); + for (const singleDateHeartbeat of heartbeatsCache) { + const heartbeatEntry = heartbeatsToSend.find((hb) => hb.agent === singleDateHeartbeat.agent); + if (!heartbeatEntry) { + heartbeatsToSend.push({ + agent: singleDateHeartbeat.agent, + dates: [singleDateHeartbeat.date] + }); + if (countBytes(heartbeatsToSend) > maxSize) { + heartbeatsToSend.pop(); + break; + } + } else { + heartbeatEntry.dates.push(singleDateHeartbeat.date); + if (countBytes(heartbeatsToSend) > maxSize) { + heartbeatEntry.dates.pop(); + break; + } + } + unsentEntries = unsentEntries.slice(1); + } + return { + heartbeatsToSend, + unsentEntries + }; +} +var HeartbeatStorageImpl = class { + constructor(app) { + this.app = app; + this._canUseIndexedDBPromise = this.runIndexedDBEnvironmentCheck(); + } + async runIndexedDBEnvironmentCheck() { + if (!isIndexedDBAvailable()) { + return false; + } else { + return validateIndexedDBOpenable().then(() => true).catch(() => false); + } + } + /** + * Read all heartbeats. + */ + async read() { + const canUseIndexedDB = await this._canUseIndexedDBPromise; + if (!canUseIndexedDB) { + return { heartbeats: [] }; + } else { + const idbHeartbeatObject = await readHeartbeatsFromIndexedDB(this.app); + return idbHeartbeatObject || { heartbeats: [] }; + } + } + // overwrite the storage with the provided heartbeats + async overwrite(heartbeatsObject) { + var _a; + const canUseIndexedDB = await this._canUseIndexedDBPromise; + if (!canUseIndexedDB) { + return; + } else { + const existingHeartbeatsObject = await this.read(); + return writeHeartbeatsToIndexedDB(this.app, { + lastSentHeartbeatDate: (_a = heartbeatsObject.lastSentHeartbeatDate) !== null && _a !== void 0 ? _a : existingHeartbeatsObject.lastSentHeartbeatDate, + heartbeats: heartbeatsObject.heartbeats + }); + } + } + // add heartbeats + async add(heartbeatsObject) { + var _a; + const canUseIndexedDB = await this._canUseIndexedDBPromise; + if (!canUseIndexedDB) { + return; + } else { + const existingHeartbeatsObject = await this.read(); + return writeHeartbeatsToIndexedDB(this.app, { + lastSentHeartbeatDate: (_a = heartbeatsObject.lastSentHeartbeatDate) !== null && _a !== void 0 ? _a : existingHeartbeatsObject.lastSentHeartbeatDate, + heartbeats: [ + ...existingHeartbeatsObject.heartbeats, + ...heartbeatsObject.heartbeats + ] + }); + } + } +}; +function countBytes(heartbeatsCache) { + return base64urlEncodeWithoutPadding( + // heartbeatsCache wrapper properties + JSON.stringify({ version: 2, heartbeats: heartbeatsCache }) + ).length; +} +function registerCoreComponents(variant) { + _registerComponent(new Component( + "platform-logger", + (container) => new PlatformLoggerServiceImpl(container), + "PRIVATE" + /* ComponentType.PRIVATE */ + )); + _registerComponent(new Component( + "heartbeat", + (container) => new HeartbeatServiceImpl(container), + "PRIVATE" + /* ComponentType.PRIVATE */ + )); + registerVersion(name$o, version$1, variant); + registerVersion(name$o, version$1, "esm2017"); + registerVersion("fire-js", ""); +} +registerCoreComponents(""); + +// node_modules/.pnpm/@firebase+database@1.0.1/node_modules/@firebase/database/dist/index.esm2017.js +var name2 = "@firebase/database"; +var version2 = "1.0.1"; +var SDK_VERSION2 = ""; +function setSDKVersion(version4) { + SDK_VERSION2 = version4; +} +var DOMStorageWrapper = class { + /** + * @param domStorage_ - The underlying storage object (e.g. localStorage or sessionStorage) + */ + constructor(domStorage_) { + this.domStorage_ = domStorage_; + this.prefix_ = "firebase:"; + } + /** + * @param key - The key to save the value under + * @param value - The value being stored, or null to remove the key. + */ + set(key, value) { + if (value == null) { + this.domStorage_.removeItem(this.prefixedName_(key)); + } else { + this.domStorage_.setItem(this.prefixedName_(key), stringify(value)); + } + } + /** + * @returns The value that was stored under this key, or null + */ + get(key) { + const storedVal = this.domStorage_.getItem(this.prefixedName_(key)); + if (storedVal == null) { + return null; + } else { + return jsonEval(storedVal); + } + } + remove(key) { + this.domStorage_.removeItem(this.prefixedName_(key)); + } + prefixedName_(name4) { + return this.prefix_ + name4; + } + toString() { + return this.domStorage_.toString(); + } +}; +var MemoryStorage = class { + constructor() { + this.cache_ = {}; + this.isInMemoryStorage = true; + } + set(key, value) { + if (value == null) { + delete this.cache_[key]; + } else { + this.cache_[key] = value; + } + } + get(key) { + if (contains(this.cache_, key)) { + return this.cache_[key]; + } + return null; + } + remove(key) { + delete this.cache_[key]; + } +}; +var createStoragefor = function(domStorageName) { + try { + if (typeof window !== "undefined" && typeof window[domStorageName] !== "undefined") { + const domStorage = window[domStorageName]; + domStorage.setItem("firebase:sentinel", "cache"); + domStorage.removeItem("firebase:sentinel"); + return new DOMStorageWrapper(domStorage); + } + } catch (e) { + } + return new MemoryStorage(); +}; +var PersistentStorage = createStoragefor("localStorage"); +var SessionStorage = createStoragefor("sessionStorage"); +var logClient = new Logger("@firebase/database"); +var LUIDGenerator = function() { + let id = 1; + return function() { + return id++; + }; +}(); +var sha1 = function(str) { + const utf8Bytes = stringToByteArray(str); + const sha12 = new Sha1(); + sha12.update(utf8Bytes); + const sha1Bytes = sha12.digest(); + return base64.encodeByteArray(sha1Bytes); +}; +var buildLogMessage_ = function(...varArgs) { + let message = ""; + for (let i = 0; i < varArgs.length; i++) { + const arg = varArgs[i]; + if (Array.isArray(arg) || arg && typeof arg === "object" && // eslint-disable-next-line @typescript-eslint/no-explicit-any + typeof arg.length === "number") { + message += buildLogMessage_.apply(null, arg); + } else if (typeof arg === "object") { + message += stringify(arg); + } else { + message += arg; + } + message += " "; + } + return message; +}; +var logger2 = null; +var firstLog_ = true; +var enableLogging$1 = function(logger_, persistent) { + assert(!persistent || logger_ === true || logger_ === false, "Can't turn on custom loggers persistently."); + if (logger_ === true) { + logClient.logLevel = LogLevel.VERBOSE; + logger2 = logClient.log.bind(logClient); + if (persistent) { + SessionStorage.set("logging_enabled", true); + } + } else if (typeof logger_ === "function") { + logger2 = logger_; + } else { + logger2 = null; + SessionStorage.remove("logging_enabled"); + } +}; +var log = function(...varArgs) { + if (firstLog_ === true) { + firstLog_ = false; + if (logger2 === null && SessionStorage.get("logging_enabled") === true) { + enableLogging$1(true); + } + } + if (logger2) { + const message = buildLogMessage_.apply(null, varArgs); + logger2(message); + } +}; +var logWrapper = function(prefix) { + return function(...varArgs) { + log(prefix, ...varArgs); + }; +}; +var error = function(...varArgs) { + const message = "FIREBASE INTERNAL ERROR: " + buildLogMessage_(...varArgs); + logClient.error(message); +}; +var fatal = function(...varArgs) { + const message = `FIREBASE FATAL ERROR: ${buildLogMessage_(...varArgs)}`; + logClient.error(message); + throw new Error(message); +}; +var warn = function(...varArgs) { + const message = "FIREBASE WARNING: " + buildLogMessage_(...varArgs); + logClient.warn(message); +}; +var warnIfPageIsSecure = function() { + if (typeof window !== "undefined" && window.location && window.location.protocol && window.location.protocol.indexOf("https:") !== -1) { + warn("Insecure Firebase access from a secure page. Please use https in calls to new Firebase()."); + } +}; +var isInvalidJSONNumber = function(data) { + return typeof data === "number" && (data !== data || // NaN + data === Number.POSITIVE_INFINITY || data === Number.NEGATIVE_INFINITY); +}; +var executeWhenDOMReady = function(fn) { + if (isNodeSdk() || document.readyState === "complete") { + fn(); + } else { + let called = false; + const wrappedFn = function() { + if (!document.body) { + setTimeout(wrappedFn, Math.floor(10)); + return; + } + if (!called) { + called = true; + fn(); + } + }; + if (document.addEventListener) { + document.addEventListener("DOMContentLoaded", wrappedFn, false); + window.addEventListener("load", wrappedFn, false); + } else if (document.attachEvent) { + document.attachEvent("onreadystatechange", () => { + if (document.readyState === "complete") { + wrappedFn(); + } + }); + window.attachEvent("onload", wrappedFn); + } + } +}; +var MIN_NAME = "[MIN_NAME]"; +var MAX_NAME = "[MAX_NAME]"; +var nameCompare = function(a, b) { + if (a === b) { + return 0; + } else if (a === MIN_NAME || b === MAX_NAME) { + return -1; + } else if (b === MIN_NAME || a === MAX_NAME) { + return 1; + } else { + const aAsInt = tryParseInt(a), bAsInt = tryParseInt(b); + if (aAsInt !== null) { + if (bAsInt !== null) { + return aAsInt - bAsInt === 0 ? a.length - b.length : aAsInt - bAsInt; + } else { + return -1; + } + } else if (bAsInt !== null) { + return 1; + } else { + return a < b ? -1 : 1; + } + } +}; +var stringCompare = function(a, b) { + if (a === b) { + return 0; + } else if (a < b) { + return -1; + } else { + return 1; + } +}; +var requireKey = function(key, obj) { + if (obj && key in obj) { + return obj[key]; + } else { + throw new Error("Missing required key (" + key + ") in object: " + stringify(obj)); + } +}; +var ObjectToUniqueKey = function(obj) { + if (typeof obj !== "object" || obj === null) { + return stringify(obj); + } + const keys = []; + for (const k in obj) { + keys.push(k); + } + keys.sort(); + let key = "{"; + for (let i = 0; i < keys.length; i++) { + if (i !== 0) { + key += ","; + } + key += stringify(keys[i]); + key += ":"; + key += ObjectToUniqueKey(obj[keys[i]]); + } + key += "}"; + return key; +}; +var splitStringBySize = function(str, segsize) { + const len = str.length; + if (len <= segsize) { + return [str]; + } + const dataSegs = []; + for (let c = 0; c < len; c += segsize) { + if (c + segsize > len) { + dataSegs.push(str.substring(c, len)); + } else { + dataSegs.push(str.substring(c, c + segsize)); + } + } + return dataSegs; +}; +function each(obj, fn) { + for (const key in obj) { + if (obj.hasOwnProperty(key)) { + fn(key, obj[key]); + } + } +} +var doubleToIEEE754String = function(v) { + assert(!isInvalidJSONNumber(v), "Invalid JSON number"); + const ebits = 11, fbits = 52; + const bias = (1 << ebits - 1) - 1; + let s, e, f, ln, i; + if (v === 0) { + e = 0; + f = 0; + s = 1 / v === -Infinity ? 1 : 0; + } else { + s = v < 0; + v = Math.abs(v); + if (v >= Math.pow(2, 1 - bias)) { + ln = Math.min(Math.floor(Math.log(v) / Math.LN2), bias); + e = ln + bias; + f = Math.round(v * Math.pow(2, fbits - ln) - Math.pow(2, fbits)); + } else { + e = 0; + f = Math.round(v / Math.pow(2, 1 - bias - fbits)); + } + } + const bits = []; + for (i = fbits; i; i -= 1) { + bits.push(f % 2 ? 1 : 0); + f = Math.floor(f / 2); + } + for (i = ebits; i; i -= 1) { + bits.push(e % 2 ? 1 : 0); + e = Math.floor(e / 2); + } + bits.push(s ? 1 : 0); + bits.reverse(); + const str = bits.join(""); + let hexByteString = ""; + for (i = 0; i < 64; i += 8) { + let hexByte = parseInt(str.substr(i, 8), 2).toString(16); + if (hexByte.length === 1) { + hexByte = "0" + hexByte; + } + hexByteString = hexByteString + hexByte; + } + return hexByteString.toLowerCase(); +}; +var isChromeExtensionContentScript = function() { + return !!(typeof window === "object" && window["chrome"] && window["chrome"]["extension"] && !/^chrome/.test(window.location.href)); +}; +var isWindowsStoreApp = function() { + return typeof Windows === "object" && typeof Windows.UI === "object"; +}; +function errorForServerCode(code, query) { + let reason = "Unknown Error"; + if (code === "too_big") { + reason = "The data requested exceeds the maximum size that can be accessed with a single request."; + } else if (code === "permission_denied") { + reason = "Client doesn't have permission to access the desired data."; + } else if (code === "unavailable") { + reason = "The service is unavailable"; + } + const error2 = new Error(code + " at " + query._path.toString() + ": " + reason); + error2.code = code.toUpperCase(); + return error2; +} +var INTEGER_REGEXP_ = new RegExp("^-?(0*)\\d{1,10}$"); +var INTEGER_32_MIN = -2147483648; +var INTEGER_32_MAX = 2147483647; +var tryParseInt = function(str) { + if (INTEGER_REGEXP_.test(str)) { + const intVal = Number(str); + if (intVal >= INTEGER_32_MIN && intVal <= INTEGER_32_MAX) { + return intVal; + } + } + return null; +}; +var exceptionGuard = function(fn) { + try { + fn(); + } catch (e) { + setTimeout(() => { + const stack = e.stack || ""; + warn("Exception was thrown by user callback.", stack); + throw e; + }, Math.floor(0)); + } +}; +var beingCrawled = function() { + const userAgent = typeof window === "object" && window["navigator"] && window["navigator"]["userAgent"] || ""; + return userAgent.search(/googlebot|google webmaster tools|bingbot|yahoo! slurp|baiduspider|yandexbot|duckduckbot/i) >= 0; +}; +var setTimeoutNonBlocking = function(fn, time) { + const timeout = setTimeout(fn, time); + if (typeof timeout === "number" && // @ts-ignore Is only defined in Deno environments. + typeof Deno !== "undefined" && // @ts-ignore Deno and unrefTimer are only defined in Deno environments. + Deno["unrefTimer"]) { + Deno.unrefTimer(timeout); + } else if (typeof timeout === "object" && timeout["unref"]) { + timeout["unref"](); + } + return timeout; +}; +var AppCheckTokenProvider = class { + constructor(appName_, appCheckProvider) { + this.appName_ = appName_; + this.appCheckProvider = appCheckProvider; + this.appCheck = appCheckProvider === null || appCheckProvider === void 0 ? void 0 : appCheckProvider.getImmediate({ optional: true }); + if (!this.appCheck) { + appCheckProvider === null || appCheckProvider === void 0 ? void 0 : appCheckProvider.get().then((appCheck) => this.appCheck = appCheck); + } + } + getToken(forceRefresh) { + if (!this.appCheck) { + return new Promise((resolve, reject) => { + setTimeout(() => { + if (this.appCheck) { + this.getToken(forceRefresh).then(resolve, reject); + } else { + resolve(null); + } + }, 0); + }); + } + return this.appCheck.getToken(forceRefresh); + } + addTokenChangeListener(listener) { + var _a; + (_a = this.appCheckProvider) === null || _a === void 0 ? void 0 : _a.get().then((appCheck) => appCheck.addTokenListener(listener)); + } + notifyForInvalidToken() { + warn(`Provided AppCheck credentials for the app named "${this.appName_}" are invalid. This usually indicates your app was not initialized correctly.`); + } +}; +var FirebaseAuthTokenProvider = class { + constructor(appName_, firebaseOptions_, authProvider_) { + this.appName_ = appName_; + this.firebaseOptions_ = firebaseOptions_; + this.authProvider_ = authProvider_; + this.auth_ = null; + this.auth_ = authProvider_.getImmediate({ optional: true }); + if (!this.auth_) { + authProvider_.onInit((auth) => this.auth_ = auth); + } + } + getToken(forceRefresh) { + if (!this.auth_) { + return new Promise((resolve, reject) => { + setTimeout(() => { + if (this.auth_) { + this.getToken(forceRefresh).then(resolve, reject); + } else { + resolve(null); + } + }, 0); + }); + } + return this.auth_.getToken(forceRefresh).catch((error2) => { + if (error2 && error2.code === "auth/token-not-initialized") { + log("Got auth/token-not-initialized error. Treating as null token."); + return null; + } else { + return Promise.reject(error2); + } + }); + } + addTokenChangeListener(listener) { + if (this.auth_) { + this.auth_.addAuthTokenListener(listener); + } else { + this.authProvider_.get().then((auth) => auth.addAuthTokenListener(listener)); + } + } + removeTokenChangeListener(listener) { + this.authProvider_.get().then((auth) => auth.removeAuthTokenListener(listener)); + } + notifyForInvalidToken() { + let errorMessage = 'Provided authentication credentials for the app named "' + this.appName_ + '" are invalid. This usually indicates your app was not initialized correctly. '; + if ("credential" in this.firebaseOptions_) { + errorMessage += 'Make sure the "credential" property provided to initializeApp() is authorized to access the specified "databaseURL" and is from the correct project.'; + } else if ("serviceAccount" in this.firebaseOptions_) { + errorMessage += 'Make sure the "serviceAccount" property provided to initializeApp() is authorized to access the specified "databaseURL" and is from the correct project.'; + } else { + errorMessage += 'Make sure the "apiKey" and "databaseURL" properties provided to initializeApp() match the values provided for your app at https://console.firebase.google.com/.'; + } + warn(errorMessage); + } +}; +var EmulatorTokenProvider = class { + constructor(accessToken) { + this.accessToken = accessToken; + } + getToken(forceRefresh) { + return Promise.resolve({ + accessToken: this.accessToken + }); + } + addTokenChangeListener(listener) { + listener(this.accessToken); + } + removeTokenChangeListener(listener) { + } + notifyForInvalidToken() { + } +}; +EmulatorTokenProvider.OWNER = "owner"; +var PROTOCOL_VERSION2 = "5"; +var VERSION_PARAM = "v"; +var TRANSPORT_SESSION_PARAM = "s"; +var REFERER_PARAM = "r"; +var FORGE_REF = "f"; +var FORGE_DOMAIN_RE = /(console\.firebase|firebase-console-\w+\.corp|firebase\.corp)\.google\.com/; +var LAST_SESSION_PARAM = "ls"; +var APPLICATION_ID_PARAM = "p"; +var APP_CHECK_TOKEN_PARAM = "ac"; +var WEBSOCKET = "websocket"; +var LONG_POLLING = "long_polling"; +var RepoInfo = class { + /** + * @param host - Hostname portion of the url for the repo + * @param secure - Whether or not this repo is accessed over ssl + * @param namespace - The namespace represented by the repo + * @param webSocketOnly - Whether to prefer websockets over all other transports (used by Nest). + * @param nodeAdmin - Whether this instance uses Admin SDK credentials + * @param persistenceKey - Override the default session persistence storage key + */ + constructor(host, secure, namespace, webSocketOnly, nodeAdmin = false, persistenceKey = "", includeNamespaceInQueryParams = false, isUsingEmulator = false) { + this.secure = secure; + this.namespace = namespace; + this.webSocketOnly = webSocketOnly; + this.nodeAdmin = nodeAdmin; + this.persistenceKey = persistenceKey; + this.includeNamespaceInQueryParams = includeNamespaceInQueryParams; + this.isUsingEmulator = isUsingEmulator; + this._host = host.toLowerCase(); + this._domain = this._host.substr(this._host.indexOf(".") + 1); + this.internalHost = PersistentStorage.get("host:" + host) || this._host; + } + isCacheableHost() { + return this.internalHost.substr(0, 2) === "s-"; + } + isCustomHost() { + return this._domain !== "firebaseio.com" && this._domain !== "firebaseio-demo.com"; + } + get host() { + return this._host; + } + set host(newHost) { + if (newHost !== this.internalHost) { + this.internalHost = newHost; + if (this.isCacheableHost()) { + PersistentStorage.set("host:" + this._host, this.internalHost); + } + } + } + toString() { + let str = this.toURLString(); + if (this.persistenceKey) { + str += "<" + this.persistenceKey + ">"; + } + return str; + } + toURLString() { + const protocol = this.secure ? "https://" : "http://"; + const query = this.includeNamespaceInQueryParams ? `?ns=${this.namespace}` : ""; + return `${protocol}${this.host}/${query}`; + } +}; +function repoInfoNeedsQueryParam(repoInfo) { + return repoInfo.host !== repoInfo.internalHost || repoInfo.isCustomHost() || repoInfo.includeNamespaceInQueryParams; +} +function repoInfoConnectionURL(repoInfo, type, params) { + assert(typeof type === "string", "typeof type must == string"); + assert(typeof params === "object", "typeof params must == object"); + let connURL; + if (type === WEBSOCKET) { + connURL = (repoInfo.secure ? "wss://" : "ws://") + repoInfo.internalHost + "/.ws?"; + } else if (type === LONG_POLLING) { + connURL = (repoInfo.secure ? "https://" : "http://") + repoInfo.internalHost + "/.lp?"; + } else { + throw new Error("Unknown connection type: " + type); + } + if (repoInfoNeedsQueryParam(repoInfo)) { + params["ns"] = repoInfo.namespace; + } + const pairs = []; + each(params, (key, value) => { + pairs.push(key + "=" + value); + }); + return connURL + pairs.join("&"); +} +var StatsCollection = class { + constructor() { + this.counters_ = {}; + } + incrementCounter(name4, amount = 1) { + if (!contains(this.counters_, name4)) { + this.counters_[name4] = 0; + } + this.counters_[name4] += amount; + } + get() { + return deepCopy(this.counters_); + } +}; +var collections = {}; +var reporters = {}; +function statsManagerGetCollection(repoInfo) { + const hashString = repoInfo.toString(); + if (!collections[hashString]) { + collections[hashString] = new StatsCollection(); + } + return collections[hashString]; +} +function statsManagerGetOrCreateReporter(repoInfo, creatorFunction) { + const hashString = repoInfo.toString(); + if (!reporters[hashString]) { + reporters[hashString] = creatorFunction(); + } + return reporters[hashString]; +} +var PacketReceiver = class { + /** + * @param onMessage_ + */ + constructor(onMessage_) { + this.onMessage_ = onMessage_; + this.pendingResponses = []; + this.currentResponseNum = 0; + this.closeAfterResponse = -1; + this.onClose = null; + } + closeAfter(responseNum, callback) { + this.closeAfterResponse = responseNum; + this.onClose = callback; + if (this.closeAfterResponse < this.currentResponseNum) { + this.onClose(); + this.onClose = null; + } + } + /** + * Each message from the server comes with a response number, and an array of data. The responseNumber + * allows us to ensure that we process them in the right order, since we can't be guaranteed that all + * browsers will respond in the same order as the requests we sent + */ + handleResponse(requestNum, data) { + this.pendingResponses[requestNum] = data; + while (this.pendingResponses[this.currentResponseNum]) { + const toProcess = this.pendingResponses[this.currentResponseNum]; + delete this.pendingResponses[this.currentResponseNum]; + for (let i = 0; i < toProcess.length; ++i) { + if (toProcess[i]) { + exceptionGuard(() => { + this.onMessage_(toProcess[i]); + }); + } + } + if (this.currentResponseNum === this.closeAfterResponse) { + if (this.onClose) { + this.onClose(); + this.onClose = null; + } + break; + } + this.currentResponseNum++; + } + } +}; +var FIREBASE_LONGPOLL_START_PARAM = "start"; +var FIREBASE_LONGPOLL_CLOSE_COMMAND = "close"; +var FIREBASE_LONGPOLL_COMMAND_CB_NAME = "pLPCommand"; +var FIREBASE_LONGPOLL_DATA_CB_NAME = "pRTLPCB"; +var FIREBASE_LONGPOLL_ID_PARAM = "id"; +var FIREBASE_LONGPOLL_PW_PARAM = "pw"; +var FIREBASE_LONGPOLL_SERIAL_PARAM = "ser"; +var FIREBASE_LONGPOLL_CALLBACK_ID_PARAM = "cb"; +var FIREBASE_LONGPOLL_SEGMENT_NUM_PARAM = "seg"; +var FIREBASE_LONGPOLL_SEGMENTS_IN_PACKET = "ts"; +var FIREBASE_LONGPOLL_DATA_PARAM = "d"; +var FIREBASE_LONGPOLL_DISCONN_FRAME_REQUEST_PARAM = "dframe"; +var MAX_URL_DATA_SIZE = 1870; +var SEG_HEADER_SIZE = 30; +var MAX_PAYLOAD_SIZE = MAX_URL_DATA_SIZE - SEG_HEADER_SIZE; +var KEEPALIVE_REQUEST_INTERVAL = 25e3; +var LP_CONNECT_TIMEOUT = 3e4; +var BrowserPollConnection = class _BrowserPollConnection { + /** + * @param connId An identifier for this connection, used for logging + * @param repoInfo The info for the endpoint to send data to. + * @param applicationId The Firebase App ID for this project. + * @param appCheckToken The AppCheck token for this client. + * @param authToken The AuthToken to use for this connection. + * @param transportSessionId Optional transportSessionid if we are + * reconnecting for an existing transport session + * @param lastSessionId Optional lastSessionId if the PersistentConnection has + * already created a connection previously + */ + constructor(connId, repoInfo, applicationId, appCheckToken, authToken, transportSessionId, lastSessionId) { + this.connId = connId; + this.repoInfo = repoInfo; + this.applicationId = applicationId; + this.appCheckToken = appCheckToken; + this.authToken = authToken; + this.transportSessionId = transportSessionId; + this.lastSessionId = lastSessionId; + this.bytesSent = 0; + this.bytesReceived = 0; + this.everConnected_ = false; + this.log_ = logWrapper(connId); + this.stats_ = statsManagerGetCollection(repoInfo); + this.urlFn = (params) => { + if (this.appCheckToken) { + params[APP_CHECK_TOKEN_PARAM] = this.appCheckToken; + } + return repoInfoConnectionURL(repoInfo, LONG_POLLING, params); + }; + } + /** + * @param onMessage - Callback when messages arrive + * @param onDisconnect - Callback with connection lost. + */ + open(onMessage, onDisconnect) { + this.curSegmentNum = 0; + this.onDisconnect_ = onDisconnect; + this.myPacketOrderer = new PacketReceiver(onMessage); + this.isClosed_ = false; + this.connectTimeoutTimer_ = setTimeout(() => { + this.log_("Timed out trying to connect."); + this.onClosed_(); + this.connectTimeoutTimer_ = null; + }, Math.floor(LP_CONNECT_TIMEOUT)); + executeWhenDOMReady(() => { + if (this.isClosed_) { + return; + } + this.scriptTagHolder = new FirebaseIFrameScriptHolder((...args) => { + const [command, arg1, arg2, arg3, arg4] = args; + this.incrementIncomingBytes_(args); + if (!this.scriptTagHolder) { + return; + } + if (this.connectTimeoutTimer_) { + clearTimeout(this.connectTimeoutTimer_); + this.connectTimeoutTimer_ = null; + } + this.everConnected_ = true; + if (command === FIREBASE_LONGPOLL_START_PARAM) { + this.id = arg1; + this.password = arg2; + } else if (command === FIREBASE_LONGPOLL_CLOSE_COMMAND) { + if (arg1) { + this.scriptTagHolder.sendNewPolls = false; + this.myPacketOrderer.closeAfter(arg1, () => { + this.onClosed_(); + }); + } else { + this.onClosed_(); + } + } else { + throw new Error("Unrecognized command received: " + command); + } + }, (...args) => { + const [pN, data] = args; + this.incrementIncomingBytes_(args); + this.myPacketOrderer.handleResponse(pN, data); + }, () => { + this.onClosed_(); + }, this.urlFn); + const urlParams = {}; + urlParams[FIREBASE_LONGPOLL_START_PARAM] = "t"; + urlParams[FIREBASE_LONGPOLL_SERIAL_PARAM] = Math.floor(Math.random() * 1e8); + if (this.scriptTagHolder.uniqueCallbackIdentifier) { + urlParams[FIREBASE_LONGPOLL_CALLBACK_ID_PARAM] = this.scriptTagHolder.uniqueCallbackIdentifier; + } + urlParams[VERSION_PARAM] = PROTOCOL_VERSION2; + if (this.transportSessionId) { + urlParams[TRANSPORT_SESSION_PARAM] = this.transportSessionId; + } + if (this.lastSessionId) { + urlParams[LAST_SESSION_PARAM] = this.lastSessionId; + } + if (this.applicationId) { + urlParams[APPLICATION_ID_PARAM] = this.applicationId; + } + if (this.appCheckToken) { + urlParams[APP_CHECK_TOKEN_PARAM] = this.appCheckToken; + } + if (typeof location !== "undefined" && location.hostname && FORGE_DOMAIN_RE.test(location.hostname)) { + urlParams[REFERER_PARAM] = FORGE_REF; + } + const connectURL = this.urlFn(urlParams); + this.log_("Connecting via long-poll to " + connectURL); + this.scriptTagHolder.addTag(connectURL, () => { + }); + }); + } + /** + * Call this when a handshake has completed successfully and we want to consider the connection established + */ + start() { + this.scriptTagHolder.startLongPoll(this.id, this.password); + this.addDisconnectPingFrame(this.id, this.password); + } + /** + * Forces long polling to be considered as a potential transport + */ + static forceAllow() { + _BrowserPollConnection.forceAllow_ = true; + } + /** + * Forces longpolling to not be considered as a potential transport + */ + static forceDisallow() { + _BrowserPollConnection.forceDisallow_ = true; + } + // Static method, use string literal so it can be accessed in a generic way + static isAvailable() { + if (isNodeSdk()) { + return false; + } else if (_BrowserPollConnection.forceAllow_) { + return true; + } else { + return !_BrowserPollConnection.forceDisallow_ && typeof document !== "undefined" && document.createElement != null && !isChromeExtensionContentScript() && !isWindowsStoreApp(); + } + } + /** + * No-op for polling + */ + markConnectionHealthy() { + } + /** + * Stops polling and cleans up the iframe + */ + shutdown_() { + this.isClosed_ = true; + if (this.scriptTagHolder) { + this.scriptTagHolder.close(); + this.scriptTagHolder = null; + } + if (this.myDisconnFrame) { + document.body.removeChild(this.myDisconnFrame); + this.myDisconnFrame = null; + } + if (this.connectTimeoutTimer_) { + clearTimeout(this.connectTimeoutTimer_); + this.connectTimeoutTimer_ = null; + } + } + /** + * Triggered when this transport is closed + */ + onClosed_() { + if (!this.isClosed_) { + this.log_("Longpoll is closing itself"); + this.shutdown_(); + if (this.onDisconnect_) { + this.onDisconnect_(this.everConnected_); + this.onDisconnect_ = null; + } + } + } + /** + * External-facing close handler. RealTime has requested we shut down. Kill our connection and tell the server + * that we've left. + */ + close() { + if (!this.isClosed_) { + this.log_("Longpoll is being closed."); + this.shutdown_(); + } + } + /** + * Send the JSON object down to the server. It will need to be stringified, base64 encoded, and then + * broken into chunks (since URLs have a small maximum length). + * @param data - The JSON data to transmit. + */ + send(data) { + const dataStr = stringify(data); + this.bytesSent += dataStr.length; + this.stats_.incrementCounter("bytes_sent", dataStr.length); + const base64data = base64Encode(dataStr); + const dataSegs = splitStringBySize(base64data, MAX_PAYLOAD_SIZE); + for (let i = 0; i < dataSegs.length; i++) { + this.scriptTagHolder.enqueueSegment(this.curSegmentNum, dataSegs.length, dataSegs[i]); + this.curSegmentNum++; + } + } + /** + * This is how we notify the server that we're leaving. + * We aren't able to send requests with DHTML on a window close event, but we can + * trigger XHR requests in some browsers (everything but Opera basically). + */ + addDisconnectPingFrame(id, pw) { + if (isNodeSdk()) { + return; + } + this.myDisconnFrame = document.createElement("iframe"); + const urlParams = {}; + urlParams[FIREBASE_LONGPOLL_DISCONN_FRAME_REQUEST_PARAM] = "t"; + urlParams[FIREBASE_LONGPOLL_ID_PARAM] = id; + urlParams[FIREBASE_LONGPOLL_PW_PARAM] = pw; + this.myDisconnFrame.src = this.urlFn(urlParams); + this.myDisconnFrame.style.display = "none"; + document.body.appendChild(this.myDisconnFrame); + } + /** + * Used to track the bytes received by this client + */ + incrementIncomingBytes_(args) { + const bytesReceived = stringify(args).length; + this.bytesReceived += bytesReceived; + this.stats_.incrementCounter("bytes_received", bytesReceived); + } +}; +var FirebaseIFrameScriptHolder = class _FirebaseIFrameScriptHolder { + /** + * @param commandCB - The callback to be called when control commands are recevied from the server. + * @param onMessageCB - The callback to be triggered when responses arrive from the server. + * @param onDisconnect - The callback to be triggered when this tag holder is closed + * @param urlFn - A function that provides the URL of the endpoint to send data to. + */ + constructor(commandCB, onMessageCB, onDisconnect, urlFn) { + this.onDisconnect = onDisconnect; + this.urlFn = urlFn; + this.outstandingRequests = /* @__PURE__ */ new Set(); + this.pendingSegs = []; + this.currentSerial = Math.floor(Math.random() * 1e8); + this.sendNewPolls = true; + if (!isNodeSdk()) { + this.uniqueCallbackIdentifier = LUIDGenerator(); + window[FIREBASE_LONGPOLL_COMMAND_CB_NAME + this.uniqueCallbackIdentifier] = commandCB; + window[FIREBASE_LONGPOLL_DATA_CB_NAME + this.uniqueCallbackIdentifier] = onMessageCB; + this.myIFrame = _FirebaseIFrameScriptHolder.createIFrame_(); + let script = ""; + if (this.myIFrame.src && this.myIFrame.src.substr(0, "javascript:".length) === "javascript:") { + const currentDomain = document.domain; + script = '