From 8eff962cab608341a6f2fedc640a0e32d96f26e2 Mon Sep 17 00:00:00 2001 From: altaf-creator Date: Sun, 9 Nov 2025 11:15:19 +0800 Subject: pain --- .../node_modules/@firebase/app/dist/index.cjs.js | 1265 ++++++++++++++++++++ 1 file changed, 1265 insertions(+) create mode 100644 frontend-old/node_modules/@firebase/app/dist/index.cjs.js (limited to 'frontend-old/node_modules/@firebase/app/dist/index.cjs.js') diff --git a/frontend-old/node_modules/@firebase/app/dist/index.cjs.js b/frontend-old/node_modules/@firebase/app/dist/index.cjs.js new file mode 100644 index 0000000..0c3b977 --- /dev/null +++ b/frontend-old/node_modules/@firebase/app/dist/index.cjs.js @@ -0,0 +1,1265 @@ +'use strict'; + +Object.defineProperty(exports, '__esModule', { value: true }); + +var component = require('@firebase/component'); +var logger$1 = require('@firebase/logger'); +var util = require('@firebase/util'); +var idb = require('idb'); + +/** + * @license + * Copyright 2019 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +class PlatformLoggerServiceImpl { + 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(); + // Loop through providers and get library/version pairs from any that are + // version components. + return providers + .map(provider => { + if (isVersionServiceProvider(provider)) { + const service = provider.getImmediate(); + return `${service.library}/${service.version}`; + } + else { + return null; + } + }) + .filter(logString => logString) + .join(' '); + } +} +/** + * + * @param provider check if this provider provides a VersionService + * + * NOTE: Using Provider<'app-version'> is a hack to indicate that the provider + * provides VersionService. The provider is not necessarily a 'app-version' + * provider. + */ +function isVersionServiceProvider(provider) { + const component = provider.getComponent(); + return component?.type === "VERSION" /* ComponentType.VERSION */; +} + +const name$q = "@firebase/app"; +const version$1 = "0.14.5"; + +/** + * @license + * Copyright 2019 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +const logger = new logger$1.Logger('@firebase/app'); + +const name$p = "@firebase/app-compat"; + +const name$o = "@firebase/analytics-compat"; + +const name$n = "@firebase/analytics"; + +const name$m = "@firebase/app-check-compat"; + +const name$l = "@firebase/app-check"; + +const name$k = "@firebase/auth"; + +const name$j = "@firebase/auth-compat"; + +const name$i = "@firebase/database"; + +const name$h = "@firebase/data-connect"; + +const name$g = "@firebase/database-compat"; + +const name$f = "@firebase/functions"; + +const name$e = "@firebase/functions-compat"; + +const name$d = "@firebase/installations"; + +const name$c = "@firebase/installations-compat"; + +const name$b = "@firebase/messaging"; + +const name$a = "@firebase/messaging-compat"; + +const name$9 = "@firebase/performance"; + +const name$8 = "@firebase/performance-compat"; + +const name$7 = "@firebase/remote-config"; + +const name$6 = "@firebase/remote-config-compat"; + +const name$5 = "@firebase/storage"; + +const name$4 = "@firebase/storage-compat"; + +const name$3 = "@firebase/firestore"; + +const name$2 = "@firebase/ai"; + +const name$1 = "@firebase/firestore-compat"; + +const name = "firebase"; +const version = "12.5.0"; + +/** + * @license + * Copyright 2019 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * The default app name + * + * @internal + */ +const DEFAULT_ENTRY_NAME = '[DEFAULT]'; +const PLATFORM_LOG_STRING = { + [name$q]: 'fire-core', + [name$p]: 'fire-core-compat', + [name$n]: 'fire-analytics', + [name$o]: 'fire-analytics-compat', + [name$l]: 'fire-app-check', + [name$m]: 'fire-app-check-compat', + [name$k]: 'fire-auth', + [name$j]: 'fire-auth-compat', + [name$i]: 'fire-rtdb', + [name$h]: 'fire-data-connect', + [name$g]: 'fire-rtdb-compat', + [name$f]: 'fire-fn', + [name$e]: 'fire-fn-compat', + [name$d]: 'fire-iid', + [name$c]: 'fire-iid-compat', + [name$b]: 'fire-fcm', + [name$a]: 'fire-fcm-compat', + [name$9]: 'fire-perf', + [name$8]: 'fire-perf-compat', + [name$7]: 'fire-rc', + [name$6]: 'fire-rc-compat', + [name$5]: 'fire-gcs', + [name$4]: 'fire-gcs-compat', + [name$3]: 'fire-fst', + [name$1]: 'fire-fst-compat', + [name$2]: 'fire-vertex', + 'fire-js': 'fire-js', // Platform identifier for JS SDK. + [name]: 'fire-js-all' +}; + +/** + * @license + * Copyright 2019 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @internal + */ +const _apps = new Map(); +/** + * @internal + */ +const _serverApps = new Map(); +/** + * Registered components. + * + * @internal + */ +// eslint-disable-next-line @typescript-eslint/no-explicit-any +const _components = new Map(); +/** + * @param component - the component being added to this app's container + * + * @internal + */ +function _addComponent(app, component) { + try { + app.container.addComponent(component); + } + catch (e) { + logger.debug(`Component ${component.name} failed to register with FirebaseApp ${app.name}`, e); + } +} +/** + * + * @internal + */ +function _addOrOverwriteComponent(app, component) { + app.container.addOrOverwriteComponent(component); +} +/** + * + * @param component - the component to register + * @returns whether or not the component is registered successfully + * + * @internal + */ +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); + // add the component to existing app instances + for (const app of _apps.values()) { + _addComponent(app, component); + } + for (const serverApp of _serverApps.values()) { + _addComponent(serverApp, component); + } + return true; +} +/** + * + * @param app - FirebaseApp instance + * @param name - service name + * + * @returns the provider for the service with the matching name + * + * @internal + */ +function _getProvider(app, name) { + const heartbeatController = app.container + .getProvider('heartbeat') + .getImmediate({ optional: true }); + if (heartbeatController) { + void heartbeatController.triggerHeartbeat(); + } + return app.container.getProvider(name); +} +/** + * + * @param app - FirebaseApp instance + * @param name - service name + * @param instanceIdentifier - service instance identifier in case the service supports multiple instances + * + * @internal + */ +function _removeServiceInstance(app, name, instanceIdentifier = DEFAULT_ENTRY_NAME) { + _getProvider(app, name).clearInstance(instanceIdentifier); +} +/** + * + * @param obj - an object of type FirebaseApp, FirebaseOptions or FirebaseAppSettings. + * + * @returns true if the provide object is of type FirebaseApp. + * + * @internal + */ +function _isFirebaseApp(obj) { + return obj.options !== undefined; +} +/** + * + * @param obj - an object of type FirebaseApp, FirebaseOptions or FirebaseAppSettings. + * + * @returns true if the provided object is of type FirebaseServerAppImpl. + * + * @internal + */ +function _isFirebaseServerAppSettings(obj) { + if (_isFirebaseApp(obj)) { + return false; + } + return ('authIdToken' in obj || + 'appCheckToken' in obj || + 'releaseOnDeref' in obj || + 'automaticDataCollectionEnabled' in obj); +} +/** + * + * @param obj - an object of type FirebaseApp. + * + * @returns true if the provided object is of type FirebaseServerAppImpl. + * + * @internal + */ +function _isFirebaseServerApp(obj) { + if (obj === null || obj === undefined) { + return false; + } + return obj.settings !== undefined; +} +/** + * Test only + * + * @internal + */ +function _clearComponents() { + _components.clear(); +} + +/** + * @license + * Copyright 2019 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +const 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", + ["server-app-deleted" /* AppError.SERVER_APP_DELETED */]: 'Firebase Server App has been 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}.', + ["finalization-registry-not-supported" /* AppError.FINALIZATION_REGISTRY_NOT_SUPPORTED */]: 'FirebaseServerApp deleteOnDeref field defined but the JS runtime does not support FinalizationRegistry.', + ["invalid-server-app-environment" /* AppError.INVALID_SERVER_APP_ENVIRONMENT */]: 'FirebaseServerApp is not for use in browser environments.' +}; +const ERROR_FACTORY = new util.ErrorFactory('app', 'Firebase', ERRORS); + +/** + * @license + * Copyright 2019 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +class FirebaseAppImpl { + constructor(options, config, container) { + this._isDeleted = false; + this._options = { ...options }; + this._config = { ...config }; + this._name = config.name; + this._automaticDataCollectionEnabled = + config.automaticDataCollectionEnabled; + this._container = container; + this.container.addComponent(new component.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" /* AppError.APP_DELETED */, { appName: this._name }); + } + } +} + +/** + * @license + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +// Parse the token and check to see if the `exp` claim is in the future. +// Reports an error to the console if the token or claim could not be parsed, or if `exp` is in +// the past. +function validateTokenTTL(base64Token, tokenName) { + const secondPart = util.base64Decode(base64Token.split('.')[1]); + if (secondPart === null) { + console.error(`FirebaseServerApp ${tokenName} is invalid: second part could not be parsed.`); + return; + } + const expClaim = JSON.parse(secondPart).exp; + if (expClaim === undefined) { + console.error(`FirebaseServerApp ${tokenName} is invalid: expiration claim could not be parsed`); + return; + } + const exp = JSON.parse(secondPart).exp * 1000; + const now = new Date().getTime(); + const diff = exp - now; + if (diff <= 0) { + console.error(`FirebaseServerApp ${tokenName} is invalid: the token has expired.`); + } +} +class FirebaseServerAppImpl extends FirebaseAppImpl { + constructor(options, serverConfig, name, container) { + // Build configuration parameters for the FirebaseAppImpl base class. + const automaticDataCollectionEnabled = serverConfig.automaticDataCollectionEnabled !== undefined + ? serverConfig.automaticDataCollectionEnabled + : true; + // Create the FirebaseAppSettings object for the FirebaseAppImp constructor. + const config = { + name, + automaticDataCollectionEnabled + }; + if (options.apiKey !== undefined) { + // Construct the parent FirebaseAppImp object. + super(options, config, container); + } + else { + const appImpl = options; + super(appImpl.options, config, container); + } + // Now construct the data for the FirebaseServerAppImpl. + this._serverConfig = { + automaticDataCollectionEnabled, + ...serverConfig + }; + // Ensure that the current time is within the `authIdtoken` window of validity. + if (this._serverConfig.authIdToken) { + validateTokenTTL(this._serverConfig.authIdToken, 'authIdToken'); + } + // Ensure that the current time is within the `appCheckToken` window of validity. + if (this._serverConfig.appCheckToken) { + validateTokenTTL(this._serverConfig.appCheckToken, 'appCheckToken'); + } + this._finalizationRegistry = null; + if (typeof FinalizationRegistry !== 'undefined') { + this._finalizationRegistry = new FinalizationRegistry(() => { + this.automaticCleanup(); + }); + } + this._refCount = 0; + this.incRefCount(this._serverConfig.releaseOnDeref); + // Do not retain a hard reference to the dref object, otherwise the FinalizationRegistry + // will never trigger. + this._serverConfig.releaseOnDeref = undefined; + serverConfig.releaseOnDeref = undefined; + registerVersion(name$q, version$1, 'serverapp'); + } + toJSON() { + return undefined; + } + get refCount() { + return this._refCount; + } + // Increment the reference count of this server app. If an object is provided, register it + // with the finalization registry. + incRefCount(obj) { + if (this.isDeleted) { + return; + } + this._refCount++; + if (obj !== undefined && this._finalizationRegistry !== null) { + this._finalizationRegistry.register(obj, this); + } + } + // Decrement the reference count. + decRefCount() { + if (this.isDeleted) { + return 0; + } + return --this._refCount; + } + // Invoked by the FinalizationRegistry callback to note that this app should go through its + // reference counts and delete itself if no reference count remain. The coordinating logic that + // handles this is in deleteApp(...). + automaticCleanup() { + void deleteApp(this); + } + get settings() { + this.checkDestroyed(); + return this._serverConfig; + } + /** + * 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("server-app-deleted" /* AppError.SERVER_APP_DELETED */); + } + } +} + +/** + * @license + * Copyright 2019 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * The current SDK version. + * + * @public + */ +const SDK_VERSION = version; +function initializeApp(_options, rawConfig = {}) { + let options = _options; + if (typeof rawConfig !== 'object') { + const name = rawConfig; + rawConfig = { name }; + } + const config = { + name: DEFAULT_ENTRY_NAME, + automaticDataCollectionEnabled: true, + ...rawConfig + }; + const name = config.name; + if (typeof name !== 'string' || !name) { + throw ERROR_FACTORY.create("bad-app-name" /* AppError.BAD_APP_NAME */, { + appName: String(name) + }); + } + options || (options = util.getDefaultAppConfig()); + if (!options) { + throw ERROR_FACTORY.create("no-options" /* AppError.NO_OPTIONS */); + } + const existingApp = _apps.get(name); + if (existingApp) { + // return the existing app if options and config deep equal the ones in the existing app. + if (util.deepEqual(options, existingApp.options) && + util.deepEqual(config, existingApp.config)) { + return existingApp; + } + else { + throw ERROR_FACTORY.create("duplicate-app" /* AppError.DUPLICATE_APP */, { appName: name }); + } + } + const container = new component.ComponentContainer(name); + for (const component of _components.values()) { + container.addComponent(component); + } + const newApp = new FirebaseAppImpl(options, config, container); + _apps.set(name, newApp); + return newApp; +} +function initializeServerApp(_options, _serverAppConfig = {}) { + if (util.isBrowser() && !util.isWebWorker()) { + // FirebaseServerApp isn't designed to be run in browsers. + throw ERROR_FACTORY.create("invalid-server-app-environment" /* AppError.INVALID_SERVER_APP_ENVIRONMENT */); + } + let firebaseOptions; + let serverAppSettings = _serverAppConfig || {}; + if (_options) { + if (_isFirebaseApp(_options)) { + firebaseOptions = _options.options; + } + else if (_isFirebaseServerAppSettings(_options)) { + serverAppSettings = _options; + } + else { + firebaseOptions = _options; + } + } + if (serverAppSettings.automaticDataCollectionEnabled === undefined) { + serverAppSettings.automaticDataCollectionEnabled = true; + } + firebaseOptions || (firebaseOptions = util.getDefaultAppConfig()); + if (!firebaseOptions) { + throw ERROR_FACTORY.create("no-options" /* AppError.NO_OPTIONS */); + } + // Build an app name based on a hash of the configuration options. + const nameObj = { + ...serverAppSettings, + ...firebaseOptions + }; + // However, Do not mangle the name based on releaseOnDeref, since it will vary between the + // construction of FirebaseServerApp instances. For example, if the object is the request headers. + if (nameObj.releaseOnDeref !== undefined) { + delete nameObj.releaseOnDeref; + } + const hashCode = (s) => { + return [...s].reduce((hash, c) => (Math.imul(31, hash) + c.charCodeAt(0)) | 0, 0); + }; + if (serverAppSettings.releaseOnDeref !== undefined) { + if (typeof FinalizationRegistry === 'undefined') { + throw ERROR_FACTORY.create("finalization-registry-not-supported" /* AppError.FINALIZATION_REGISTRY_NOT_SUPPORTED */, {}); + } + } + const nameString = '' + hashCode(JSON.stringify(nameObj)); + const existingApp = _serverApps.get(nameString); + if (existingApp) { + existingApp.incRefCount(serverAppSettings.releaseOnDeref); + return existingApp; + } + const container = new component.ComponentContainer(nameString); + for (const component of _components.values()) { + container.addComponent(component); + } + const newApp = new FirebaseServerAppImpl(firebaseOptions, serverAppSettings, nameString, container); + _serverApps.set(nameString, newApp); + return newApp; +} +/** + * Retrieves a {@link @firebase/app#FirebaseApp} instance. + * + * When called with no arguments, the default app is returned. When an app name + * is provided, the app corresponding to that name is returned. + * + * An exception is thrown if the app being retrieved has not yet been + * initialized. + * + * @example + * ```javascript + * // Return the default app + * const app = getApp(); + * ``` + * + * @example + * ```javascript + * // Return a named app + * const otherApp = getApp("otherApp"); + * ``` + * + * @param name - Optional name of the app to return. If no name is + * provided, the default is `"[DEFAULT]"`. + * + * @returns The app corresponding to the provided app name. + * If no app name is provided, the default app is returned. + * + * @public + */ +function getApp(name = DEFAULT_ENTRY_NAME) { + const app = _apps.get(name); + if (!app && name === DEFAULT_ENTRY_NAME && util.getDefaultAppConfig()) { + return initializeApp(); + } + if (!app) { + throw ERROR_FACTORY.create("no-app" /* AppError.NO_APP */, { appName: name }); + } + return app; +} +/** + * A (read-only) array of all initialized apps. + * @public + */ +function getApps() { + return Array.from(_apps.values()); +} +/** + * Renders this app unusable and frees the resources of all associated + * services. + * + * @example + * ```javascript + * deleteApp(app) + * .then(function() { + * console.log("App deleted successfully"); + * }) + * .catch(function(error) { + * console.log("Error deleting app:", error); + * }); + * ``` + * + * @public + */ +async function deleteApp(app) { + let cleanupProviders = false; + const name = app.name; + if (_apps.has(name)) { + cleanupProviders = true; + _apps.delete(name); + } + else if (_serverApps.has(name)) { + const firebaseServerApp = app; + if (firebaseServerApp.decRefCount() <= 0) { + _serverApps.delete(name); + cleanupProviders = true; + } + } + if (cleanupProviders) { + await Promise.all(app.container + .getProviders() + .map(provider => provider.delete())); + app.isDeleted = true; + } +} +/** + * Registers a library's name and version for platform logging purposes. + * @param library - Name of 1p or 3p library (e.g. firestore, angularfire) + * @param version - Current version of that library. + * @param variant - Bundle variant, e.g., node, rn, etc. + * + * @public + */ +function registerVersion(libraryKeyOrName, version, variant) { + // TODO: We can use this check to whitelist strings when/if we set up + // a good whitelist system. + let library = PLATFORM_LOG_STRING[libraryKeyOrName] ?? libraryKeyOrName; + if (variant) { + library += `-${variant}`; + } + const libraryMismatch = library.match(/\s|\//); + const versionMismatch = version.match(/\s|\//); + if (libraryMismatch || versionMismatch) { + const warning = [ + `Unable to register library "${library}" with version "${version}":` + ]; + if (libraryMismatch) { + warning.push(`library name "${library}" contains illegal characters (whitespace or "/")`); + } + if (libraryMismatch && versionMismatch) { + warning.push('and'); + } + if (versionMismatch) { + warning.push(`version name "${version}" contains illegal characters (whitespace or "/")`); + } + logger.warn(warning.join(' ')); + return; + } + _registerComponent(new component.Component(`${library}-version`, () => ({ library, version }), "VERSION" /* ComponentType.VERSION */)); +} +/** + * Sets log handler for all Firebase SDKs. + * @param logCallback - An optional custom log handler that executes user code whenever + * the Firebase SDK makes a logging call. + * + * @public + */ +function onLog(logCallback, options) { + if (logCallback !== null && typeof logCallback !== 'function') { + throw ERROR_FACTORY.create("invalid-log-argument" /* AppError.INVALID_LOG_ARGUMENT */); + } + logger$1.setUserLogHandler(logCallback, options); +} +/** + * Sets log level for all Firebase SDKs. + * + * All of the log types above the current log level are captured (i.e. if + * you set the log level to `info`, errors are logged, but `debug` and + * `verbose` logs are not). + * + * @public + */ +function setLogLevel(logLevel) { + logger$1.setLogLevel(logLevel); +} + +/** + * @license + * Copyright 2021 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +const DB_NAME = 'firebase-heartbeat-database'; +const DB_VERSION = 1; +const STORE_NAME = 'firebase-heartbeat-store'; +let dbPromise = null; +function getDbPromise() { + if (!dbPromise) { + dbPromise = idb.openDB(DB_NAME, DB_VERSION, { + upgrade: (db, oldVersion) => { + // We don't use 'break' in this switch statement, the fall-through + // behavior is what we want, because if there are multiple versions between + // the old version and the current version, we want ALL the migrations + // that correspond to those versions to run, not only the last one. + // eslint-disable-next-line default-case + switch (oldVersion) { + case 0: + try { + db.createObjectStore(STORE_NAME); + } + catch (e) { + // Safari/iOS browsers throw occasional exceptions on + // db.createObjectStore() that may be a bug. Avoid blocking + // the rest of the app functionality. + console.warn(e); + } + } + } + }).catch(e => { + throw ERROR_FACTORY.create("idb-open" /* AppError.IDB_OPEN */, { + originalErrorMessage: e.message + }); + }); + } + return dbPromise; +} +async function readHeartbeatsFromIndexedDB(app) { + try { + const db = await getDbPromise(); + const tx = db.transaction(STORE_NAME); + const result = await tx.objectStore(STORE_NAME).get(computeKey(app)); + // We already have the value but tx.done can throw, + // so we need to await it here to catch errors + await tx.done; + return result; + } + catch (e) { + if (e instanceof util.FirebaseError) { + logger.warn(e.message); + } + else { + const idbGetError = ERROR_FACTORY.create("idb-get" /* AppError.IDB_GET */, { + originalErrorMessage: 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 util.FirebaseError) { + logger.warn(e.message); + } + else { + const idbGetError = ERROR_FACTORY.create("idb-set" /* AppError.IDB_WRITE */, { + originalErrorMessage: e?.message + }); + logger.warn(idbGetError.message); + } + } +} +function computeKey(app) { + return `${app.name}!${app.options.appId}`; +} + +/** + * @license + * Copyright 2021 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +const MAX_HEADER_BYTES = 1024; +const MAX_NUM_STORED_HEARTBEATS = 30; +class HeartbeatServiceImpl { + constructor(container) { + this.container = container; + /** + * In-memory cache for heartbeats, used by getHeartbeatsHeader() to generate + * the header string. + * Stores one record per date. This will be consolidated into the standard + * format of one record per user agent string before being sent as a header. + * Populated from indexedDB when the controller is instantiated and should + * be kept in sync with indexedDB. + * Leave public for easier testing. + */ + 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() { + try { + const platformLogger = this.container + .getProvider('platform-logger') + .getImmediate(); + // This is the "Firebase user agent" string from the platform logger + // service, not the browser user agent. + const agent = platformLogger.getPlatformInfoString(); + const date = getUTCDateString(); + if (this._heartbeatsCache?.heartbeats == null) { + this._heartbeatsCache = await this._heartbeatsCachePromise; + // If we failed to construct a heartbeats cache, then return immediately. + if (this._heartbeatsCache?.heartbeats == null) { + return; + } + } + // Do not store a heartbeat if one is already stored for this day + // or if a header has already been sent today. + if (this._heartbeatsCache.lastSentHeartbeatDate === date || + this._heartbeatsCache.heartbeats.some(singleDateHeartbeat => singleDateHeartbeat.date === date)) { + return; + } + else { + // There is no entry for this date. Create one. + this._heartbeatsCache.heartbeats.push({ date, agent }); + // If the number of stored heartbeats exceeds the maximum number of stored heartbeats, remove the heartbeat with the earliest date. + // Since this is executed each time a heartbeat is pushed, the limit can only be exceeded by one, so only one needs to be removed. + if (this._heartbeatsCache.heartbeats.length > MAX_NUM_STORED_HEARTBEATS) { + const earliestHeartbeatIdx = getEarliestHeartbeatIdx(this._heartbeatsCache.heartbeats); + this._heartbeatsCache.heartbeats.splice(earliestHeartbeatIdx, 1); + } + } + return this._storage.overwrite(this._heartbeatsCache); + } + catch (e) { + logger.warn(e); + } + } + /** + * 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() { + try { + if (this._heartbeatsCache === null) { + await this._heartbeatsCachePromise; + } + // If it's still null or the array is empty, there is no data to send. + if (this._heartbeatsCache?.heartbeats == null || + this._heartbeatsCache.heartbeats.length === 0) { + return ''; + } + const date = getUTCDateString(); + // Extract as many heartbeats from the cache as will fit under the size limit. + const { heartbeatsToSend, unsentEntries } = extractHeartbeatsForHeader(this._heartbeatsCache.heartbeats); + const headerString = util.base64urlEncodeWithoutPadding(JSON.stringify({ version: 2, heartbeats: heartbeatsToSend })); + // Store last sent date to prevent another being logged/sent for the same day. + this._heartbeatsCache.lastSentHeartbeatDate = date; + if (unsentEntries.length > 0) { + // Store any unsent entries if they exist. + this._heartbeatsCache.heartbeats = unsentEntries; + // This seems more likely than emptying the array (below) to lead to some odd state + // since the cache isn't empty and this will be called again on the next request, + // and is probably safest if we await it. + await this._storage.overwrite(this._heartbeatsCache); + } + else { + this._heartbeatsCache.heartbeats = []; + // Do not wait for this, to reduce latency. + void this._storage.overwrite(this._heartbeatsCache); + } + return headerString; + } + catch (e) { + logger.warn(e); + return ''; + } + } +} +function getUTCDateString() { + const today = new Date(); + // Returns date format 'YYYY-MM-DD' + return today.toISOString().substring(0, 10); +} +function extractHeartbeatsForHeader(heartbeatsCache, maxSize = MAX_HEADER_BYTES) { + // Heartbeats grouped by user agent in the standard format to be sent in + // the header. + const heartbeatsToSend = []; + // Single date format heartbeats that are not sent. + let unsentEntries = heartbeatsCache.slice(); + for (const singleDateHeartbeat of heartbeatsCache) { + // Look for an existing entry with the same user agent. + const heartbeatEntry = heartbeatsToSend.find(hb => hb.agent === singleDateHeartbeat.agent); + if (!heartbeatEntry) { + // If no entry for this user agent exists, create one. + heartbeatsToSend.push({ + agent: singleDateHeartbeat.agent, + dates: [singleDateHeartbeat.date] + }); + if (countBytes(heartbeatsToSend) > maxSize) { + // If the header would exceed max size, remove the added heartbeat + // entry and stop adding to the header. + heartbeatsToSend.pop(); + break; + } + } + else { + heartbeatEntry.dates.push(singleDateHeartbeat.date); + // If the header would exceed max size, remove the added date + // and stop adding to the header. + if (countBytes(heartbeatsToSend) > maxSize) { + heartbeatEntry.dates.pop(); + break; + } + } + // Pop unsent entry from queue. (Skipped if adding the entry exceeded + // quota and the loop breaks early.) + unsentEntries = unsentEntries.slice(1); + } + return { + heartbeatsToSend, + unsentEntries + }; +} +class HeartbeatStorageImpl { + constructor(app) { + this.app = app; + this._canUseIndexedDBPromise = this.runIndexedDBEnvironmentCheck(); + } + async runIndexedDBEnvironmentCheck() { + if (!util.isIndexedDBAvailable()) { + return false; + } + else { + return util.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); + if (idbHeartbeatObject?.heartbeats) { + return idbHeartbeatObject; + } + else { + return { heartbeats: [] }; + } + } + } + // overwrite the storage with the provided heartbeats + async overwrite(heartbeatsObject) { + const canUseIndexedDB = await this._canUseIndexedDBPromise; + if (!canUseIndexedDB) { + return; + } + else { + const existingHeartbeatsObject = await this.read(); + return writeHeartbeatsToIndexedDB(this.app, { + lastSentHeartbeatDate: heartbeatsObject.lastSentHeartbeatDate ?? + existingHeartbeatsObject.lastSentHeartbeatDate, + heartbeats: heartbeatsObject.heartbeats + }); + } + } + // add heartbeats + async add(heartbeatsObject) { + const canUseIndexedDB = await this._canUseIndexedDBPromise; + if (!canUseIndexedDB) { + return; + } + else { + const existingHeartbeatsObject = await this.read(); + return writeHeartbeatsToIndexedDB(this.app, { + lastSentHeartbeatDate: heartbeatsObject.lastSentHeartbeatDate ?? + existingHeartbeatsObject.lastSentHeartbeatDate, + heartbeats: [ + ...existingHeartbeatsObject.heartbeats, + ...heartbeatsObject.heartbeats + ] + }); + } + } +} +/** + * Calculate bytes of a HeartbeatsByUserAgent array after being wrapped + * in a platform logging header JSON object, stringified, and converted + * to base 64. + */ +function countBytes(heartbeatsCache) { + // base64 has a restricted set of characters, all of which should be 1 byte. + return util.base64urlEncodeWithoutPadding( + // heartbeatsCache wrapper properties + JSON.stringify({ version: 2, heartbeats: heartbeatsCache })).length; +} +/** + * Returns the index of the heartbeat with the earliest date. + * If the heartbeats array is empty, -1 is returned. + */ +function getEarliestHeartbeatIdx(heartbeats) { + if (heartbeats.length === 0) { + return -1; + } + let earliestHeartbeatIdx = 0; + let earliestHeartbeatDate = heartbeats[0].date; + for (let i = 1; i < heartbeats.length; i++) { + if (heartbeats[i].date < earliestHeartbeatDate) { + earliestHeartbeatDate = heartbeats[i].date; + earliestHeartbeatIdx = i; + } + } + return earliestHeartbeatIdx; +} + +/** + * @license + * Copyright 2019 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +function registerCoreComponents(variant) { + _registerComponent(new component.Component('platform-logger', container => new PlatformLoggerServiceImpl(container), "PRIVATE" /* ComponentType.PRIVATE */)); + _registerComponent(new component.Component('heartbeat', container => new HeartbeatServiceImpl(container), "PRIVATE" /* ComponentType.PRIVATE */)); + // Register `app` package. + registerVersion(name$q, version$1, variant); + // BUILD_TARGET will be replaced by values like esm, cjs, etc during the compilation + registerVersion(name$q, version$1, 'cjs2020'); + // Register platform SDK identifier (no version). + registerVersion('fire-js', ''); +} + +/** + * Firebase App + * + * @remarks This package coordinates the communication between the different Firebase components + * @packageDocumentation + */ +registerCoreComponents('node'); + +Object.defineProperty(exports, 'FirebaseError', { + enumerable: true, + get: function () { return util.FirebaseError; } +}); +exports.SDK_VERSION = SDK_VERSION; +exports._DEFAULT_ENTRY_NAME = DEFAULT_ENTRY_NAME; +exports._addComponent = _addComponent; +exports._addOrOverwriteComponent = _addOrOverwriteComponent; +exports._apps = _apps; +exports._clearComponents = _clearComponents; +exports._components = _components; +exports._getProvider = _getProvider; +exports._isFirebaseApp = _isFirebaseApp; +exports._isFirebaseServerApp = _isFirebaseServerApp; +exports._isFirebaseServerAppSettings = _isFirebaseServerAppSettings; +exports._registerComponent = _registerComponent; +exports._removeServiceInstance = _removeServiceInstance; +exports._serverApps = _serverApps; +exports.deleteApp = deleteApp; +exports.getApp = getApp; +exports.getApps = getApps; +exports.initializeApp = initializeApp; +exports.initializeServerApp = initializeServerApp; +exports.onLog = onLog; +exports.registerVersion = registerVersion; +exports.setLogLevel = setLogLevel; +//# sourceMappingURL=index.cjs.js.map -- cgit v1.2.3