firebase
Version:
Firebase JavaScript library for web and Node.js
1,279 lines (1,233 loc) • 60.6 kB
JavaScript
/*! *****************************************************************************
Copyright (c) Microsoft Corporation.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
***************************************************************************** */
/* global Reflect, Promise */
var extendStatics = function(d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
function __extends(d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
}
function __awaiter(thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
}
function __generator(thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
}
function __values(o) {
var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
if (m) return m.call(o);
if (o && typeof o.length === "number") return {
next: function () {
if (o && i >= o.length) o = void 0;
return { value: o && o[i++], done: !o };
}
};
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
}
function __read(o, n) {
var m = typeof Symbol === "function" && o[Symbol.iterator];
if (!m) return o;
var i = m.call(o), r, ar = [], e;
try {
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
}
catch (error) { e = { error: error }; }
finally {
try {
if (r && !r.done && (m = i["return"])) m.call(i);
}
finally { if (e) throw e.error; }
}
return ar;
}
function __spreadArray(to, from) {
for (var i = 0, il = from.length, j = to.length; i < il; i++, j++)
to[j] = from[i];
return to;
}
/**
* @license
* Copyright 2017 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.
*/
var Deferred = /** @class */ (function () {
function Deferred() {
var _this = this;
this.reject = function () { };
this.resolve = function () { };
this.promise = new Promise(function (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.
*/
Deferred.prototype.wrapCallback = function (callback) {
var _this = this;
return function (error, value) {
if (error) {
_this.reject(error);
}
else {
_this.resolve(value);
}
if (typeof callback === 'function') {
// Attaching noop handler just in case developer wasn't expecting
// promises
_this.promise.catch(function () { });
// Some of our callbacks don't expect a value and our own tests
// assert that the parameter length is 1
if (callback.length === 1) {
callback(error);
}
else {
callback(error, value);
}
}
};
};
return Deferred;
}());
/**
* @license
* Copyright 2017 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.
*/
var ERROR_NAME = 'FirebaseError';
// Based on code from:
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error#Custom_Error_Types
var FirebaseError = /** @class */ (function (_super) {
__extends(FirebaseError, _super);
function FirebaseError(code, message, customData) {
var _this = _super.call(this, message) || this;
_this.code = code;
_this.customData = customData;
_this.name = ERROR_NAME;
// Fix For ES5
// https://github.com/Microsoft/TypeScript-wiki/blob/master/Breaking-Changes.md#extending-built-ins-like-error-array-and-map-may-no-longer-work
Object.setPrototypeOf(_this, FirebaseError.prototype);
// Maintains proper stack trace for where our error was thrown.
// Only available on V8.
if (Error.captureStackTrace) {
Error.captureStackTrace(_this, ErrorFactory.prototype.create);
}
return _this;
}
return FirebaseError;
}(Error));
var ErrorFactory = /** @class */ (function () {
function ErrorFactory(service, serviceName, errors) {
this.service = service;
this.serviceName = serviceName;
this.errors = errors;
}
ErrorFactory.prototype.create = function (code) {
var data = [];
for (var _i = 1; _i < arguments.length; _i++) {
data[_i - 1] = arguments[_i];
}
var customData = data[0] || {};
var fullCode = this.service + "/" + code;
var template = this.errors[code];
var message = template ? replaceTemplate(template, customData) : 'Error';
// Service Name: Error message (service/code).
var fullMessage = this.serviceName + ": " + message + " (" + fullCode + ").";
var error = new FirebaseError(fullCode, fullMessage, customData);
return error;
};
return ErrorFactory;
}());
function replaceTemplate(template, data) {
return template.replace(PATTERN, function (_, key) {
var value = data[key];
return value != null ? String(value) : "<" + key + "?>";
});
}
var PATTERN = /\{\$([^}]+)}/g;
/**
* Deep equal two objects. Support Arrays and Objects.
*/
function deepEqual(a, b) {
if (a === b) {
return true;
}
var aKeys = Object.keys(a);
var bKeys = Object.keys(b);
for (var _i = 0, aKeys_1 = aKeys; _i < aKeys_1.length; _i++) {
var k = aKeys_1[_i];
if (!bKeys.includes(k)) {
return false;
}
var aProp = a[k];
var bProp = b[k];
if (isObject(aProp) && isObject(bProp)) {
if (!deepEqual(aProp, bProp)) {
return false;
}
}
else if (aProp !== bProp) {
return false;
}
}
for (var _a = 0, bKeys_1 = bKeys; _a < bKeys_1.length; _a++) {
var k = bKeys_1[_a];
if (!aKeys.includes(k)) {
return false;
}
}
return true;
}
function isObject(thing) {
return thing !== null && typeof thing === 'object';
}
/**
* Component for service name T, e.g. `auth`, `auth-internal`
*/
var Component = /** @class */ (function () {
/**
*
* @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
*/
function Component(name, instanceFactory, type) {
this.name = name;
this.instanceFactory = instanceFactory;
this.type = type;
this.multipleInstances = false;
/**
* Properties to be added to the service namespace
*/
this.serviceProps = {};
this.instantiationMode = "LAZY" /* LAZY */;
this.onInstanceCreated = null;
}
Component.prototype.setInstantiationMode = function (mode) {
this.instantiationMode = mode;
return this;
};
Component.prototype.setMultipleInstances = function (multipleInstances) {
this.multipleInstances = multipleInstances;
return this;
};
Component.prototype.setServiceProps = function (props) {
this.serviceProps = props;
return this;
};
Component.prototype.setInstanceCreatedCallback = function (callback) {
this.onInstanceCreated = callback;
return this;
};
return Component;
}());
/**
* @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.
*/
var DEFAULT_ENTRY_NAME$1 = '[DEFAULT]';
/**
* @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.
*/
/**
* Provider for instance for service name T, e.g. 'auth', 'auth-internal'
* NameServiceMapping[T] is an alias for the type of the instance
*/
var Provider = /** @class */ (function () {
function Provider(name, container) {
this.name = name;
this.container = container;
this.component = null;
this.instances = new Map();
this.instancesDeferred = new Map();
this.instancesOptions = new Map();
this.onInitCallbacks = new Map();
}
/**
* @param identifier A provider can provide mulitple instances of a service
* if this.component.multipleInstances is true.
*/
Provider.prototype.get = function (identifier) {
// if multipleInstances is not supported, use the default name
var normalizedIdentifier = this.normalizeInstanceIdentifier(identifier);
if (!this.instancesDeferred.has(normalizedIdentifier)) {
var deferred = new Deferred();
this.instancesDeferred.set(normalizedIdentifier, deferred);
if (this.isInitialized(normalizedIdentifier) ||
this.shouldAutoInitialize()) {
// initialize the service if it can be auto-initialized
try {
var instance = this.getOrInitializeService({
instanceIdentifier: normalizedIdentifier
});
if (instance) {
deferred.resolve(instance);
}
}
catch (e) {
// when the instance factory throws an exception during get(), it should not cause
// a fatal error. We just return the unresolved promise in this case.
}
}
}
return this.instancesDeferred.get(normalizedIdentifier).promise;
};
Provider.prototype.getImmediate = function (options) {
var _a;
// if multipleInstances is not supported, use the default name
var normalizedIdentifier = this.normalizeInstanceIdentifier(options === null || options === void 0 ? void 0 : options.identifier);
var 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 {
// In case a component is not initialized and should/can not be auto-initialized at the moment, return null if the optional flag is set, or throw
if (optional) {
return null;
}
else {
throw Error("Service " + this.name + " is not available");
}
}
};
Provider.prototype.getComponent = function () {
return this.component;
};
Provider.prototype.setComponent = function (component) {
var e_1, _a;
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;
// return early without attempting to initialize the component if the component requires explicit initialization (calling `Provider.initialize()`)
if (!this.shouldAutoInitialize()) {
return;
}
// if the service is eager, initialize the default instance
if (isComponentEager(component)) {
try {
this.getOrInitializeService({ instanceIdentifier: DEFAULT_ENTRY_NAME$1 });
}
catch (e) {
// when the instance factory for an eager Component throws an exception during the eager
// initialization, it should not cause a fatal error.
// TODO: Investigate if we need to make it configurable, because some component may want to cause
// a fatal error in this case?
}
}
try {
// Create service instances for the pending promises and resolve them
// NOTE: if this.multipleInstances is false, only the default instance will be created
// and all promises with resolve with it regardless of the identifier.
for (var _b = __values(this.instancesDeferred.entries()), _c = _b.next(); !_c.done; _c = _b.next()) {
var _d = __read(_c.value, 2), instanceIdentifier = _d[0], instanceDeferred = _d[1];
var normalizedIdentifier = this.normalizeInstanceIdentifier(instanceIdentifier);
try {
// `getOrInitializeService()` should always return a valid instance since a component is guaranteed. use ! to make typescript happy.
var instance = this.getOrInitializeService({
instanceIdentifier: normalizedIdentifier
});
instanceDeferred.resolve(instance);
}
catch (e) {
// when the instance factory throws an exception, it should not cause
// a fatal error. We just leave the promise unresolved.
}
}
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
}
finally { if (e_1) throw e_1.error; }
}
};
Provider.prototype.clearInstance = function (identifier) {
if (identifier === void 0) { identifier = DEFAULT_ENTRY_NAME$1; }
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?
Provider.prototype.delete = function () {
return __awaiter(this, void 0, void 0, function () {
var services;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
services = Array.from(this.instances.values());
return [4 /*yield*/, Promise.all(__spreadArray(__spreadArray([], __read(services
.filter(function (service) { return 'INTERNAL' in service; }) // legacy services
// eslint-disable-next-line @typescript-eslint/no-explicit-any
.map(function (service) { return service.INTERNAL.delete(); }))), __read(services
.filter(function (service) { return '_delete' in service; }) // modularized services
// eslint-disable-next-line @typescript-eslint/no-explicit-any
.map(function (service) { return service._delete(); }))))];
case 1:
_a.sent();
return [2 /*return*/];
}
});
});
};
Provider.prototype.isComponentSet = function () {
return this.component != null;
};
Provider.prototype.isInitialized = function (identifier) {
if (identifier === void 0) { identifier = DEFAULT_ENTRY_NAME$1; }
return this.instances.has(identifier);
};
Provider.prototype.getOptions = function (identifier) {
if (identifier === void 0) { identifier = DEFAULT_ENTRY_NAME$1; }
return this.instancesOptions.get(identifier) || {};
};
Provider.prototype.initialize = function (opts) {
var e_2, _a;
if (opts === void 0) { opts = {}; }
var _b = opts.options, options = _b === void 0 ? {} : _b;
var 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");
}
var instance = this.getOrInitializeService({
instanceIdentifier: normalizedIdentifier,
options: options
});
try {
// resolve any pending promise waiting for the service instance
for (var _c = __values(this.instancesDeferred.entries()), _d = _c.next(); !_d.done; _d = _c.next()) {
var _e = __read(_d.value, 2), instanceIdentifier = _e[0], instanceDeferred = _e[1];
var normalizedDeferredIdentifier = this.normalizeInstanceIdentifier(instanceIdentifier);
if (normalizedIdentifier === normalizedDeferredIdentifier) {
instanceDeferred.resolve(instance);
}
}
}
catch (e_2_1) { e_2 = { error: e_2_1 }; }
finally {
try {
if (_d && !_d.done && (_a = _c.return)) _a.call(_c);
}
finally { if (e_2) throw e_2.error; }
}
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
*/
Provider.prototype.onInit = function (callback, identifier) {
var _a;
var normalizedIdentifier = this.normalizeInstanceIdentifier(identifier);
var existingCallbacks = (_a = this.onInitCallbacks.get(normalizedIdentifier)) !== null && _a !== void 0 ? _a : new Set();
existingCallbacks.add(callback);
this.onInitCallbacks.set(normalizedIdentifier, existingCallbacks);
var existingInstance = this.instances.get(normalizedIdentifier);
if (existingInstance) {
callback(existingInstance, normalizedIdentifier);
}
return function () {
existingCallbacks.delete(callback);
};
};
/**
* Invoke onInit callbacks synchronously
* @param instance the service instance`
*/
Provider.prototype.invokeOnInitCallbacks = function (instance, identifier) {
var e_3, _a;
var callbacks = this.onInitCallbacks.get(identifier);
if (!callbacks) {
return;
}
try {
for (var callbacks_1 = __values(callbacks), callbacks_1_1 = callbacks_1.next(); !callbacks_1_1.done; callbacks_1_1 = callbacks_1.next()) {
var callback = callbacks_1_1.value;
try {
callback(instance, identifier);
}
catch (_b) {
// ignore errors in the onInit callback
}
}
}
catch (e_3_1) { e_3 = { error: e_3_1 }; }
finally {
try {
if (callbacks_1_1 && !callbacks_1_1.done && (_a = callbacks_1.return)) _a.call(callbacks_1);
}
finally { if (e_3) throw e_3.error; }
}
};
Provider.prototype.getOrInitializeService = function (_a) {
var instanceIdentifier = _a.instanceIdentifier, _b = _a.options, options = _b === void 0 ? {} : _b;
var instance = this.instances.get(instanceIdentifier);
if (!instance && this.component) {
instance = this.component.instanceFactory(this.container, {
instanceIdentifier: normalizeIdentifierForFactory(instanceIdentifier),
options: options
});
this.instances.set(instanceIdentifier, instance);
this.instancesOptions.set(instanceIdentifier, options);
/**
* Invoke onInit listeners.
* Note this.component.onInstanceCreated is different, which is used by the component creator,
* while onInit listeners are registered by consumers of the provider.
*/
this.invokeOnInitCallbacks(instance, instanceIdentifier);
/**
* Order is important
* onInstanceCreated() should be called after this.instances.set(instanceIdentifier, instance); which
* makes `isInitialized()` return true.
*/
if (this.component.onInstanceCreated) {
try {
this.component.onInstanceCreated(this.container, instanceIdentifier, instance);
}
catch (_c) {
// ignore errors in the onInstanceCreatedCallback
}
}
}
return instance || null;
};
Provider.prototype.normalizeInstanceIdentifier = function (identifier) {
if (identifier === void 0) { identifier = DEFAULT_ENTRY_NAME$1; }
if (this.component) {
return this.component.multipleInstances ? identifier : DEFAULT_ENTRY_NAME$1;
}
else {
return identifier; // assume multiple instances are supported before the component is provided.
}
};
Provider.prototype.shouldAutoInitialize = function () {
return (!!this.component &&
this.component.instantiationMode !== "EXPLICIT" /* EXPLICIT */);
};
return Provider;
}());
// undefined should be passed to the service factory for the default instance
function normalizeIdentifierForFactory(identifier) {
return identifier === DEFAULT_ENTRY_NAME$1 ? undefined : identifier;
}
function isComponentEager(component) {
return component.instantiationMode === "EAGER" /* EAGER */;
}
/**
* @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.
*/
/**
* ComponentContainer that provides Providers for service name T, e.g. `auth`, `auth-internal`
*/
var ComponentContainer = /** @class */ (function () {
function ComponentContainer(name) {
this.name = name;
this.providers = 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
*/
ComponentContainer.prototype.addComponent = function (component) {
var provider = this.getProvider(component.name);
if (provider.isComponentSet()) {
throw new Error("Component " + component.name + " has already been registered with " + this.name);
}
provider.setComponent(component);
};
ComponentContainer.prototype.addOrOverwriteComponent = function (component) {
var provider = this.getProvider(component.name);
if (provider.isComponentSet()) {
// delete the existing provider from the container, so we can register the new component
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.
*/
ComponentContainer.prototype.getProvider = function (name) {
if (this.providers.has(name)) {
return this.providers.get(name);
}
// create a Provider for a service that hasn't registered with Firebase
var provider = new Provider(name, this);
this.providers.set(name, provider);
return provider;
};
ComponentContainer.prototype.getProviders = function () {
return Array.from(this.providers.values());
};
return ComponentContainer;
}());
/**
* @license
* Copyright 2017 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.
*/
var _a;
/**
* A container for all of the Logger instances
*/
var instances = [];
/**
* The JS SDK supports 5 log levels and also allows a user the ability to
* silence the logs altogether.
*
* The order is a follows:
* DEBUG < VERBOSE < INFO < WARN < ERROR
*
* All of the log types above the current log level will be captured (i.e. if
* you set the log level to `INFO`, errors will still be logged, but `DEBUG` and
* `VERBOSE` logs will not)
*/
var LogLevel;
(function (LogLevel) {
LogLevel[LogLevel["DEBUG"] = 0] = "DEBUG";
LogLevel[LogLevel["VERBOSE"] = 1] = "VERBOSE";
LogLevel[LogLevel["INFO"] = 2] = "INFO";
LogLevel[LogLevel["WARN"] = 3] = "WARN";
LogLevel[LogLevel["ERROR"] = 4] = "ERROR";
LogLevel[LogLevel["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
};
/**
* The default log level
*/
var defaultLogLevel = LogLevel.INFO;
/**
* By default, `console.debug` is not displayed in the developer console (in
* chrome). To avoid forcing users to have to opt-in to these logs twice
* (i.e. once for firebase, and once in the console), we are sending `DEBUG`
* logs to the `console.log` function.
*/
var ConsoleMethod = (_a = {},
_a[LogLevel.DEBUG] = 'log',
_a[LogLevel.VERBOSE] = 'log',
_a[LogLevel.INFO] = 'info',
_a[LogLevel.WARN] = 'warn',
_a[LogLevel.ERROR] = 'error',
_a);
/**
* The default log handler will forward DEBUG, VERBOSE, INFO, WARN, and ERROR
* messages on to their corresponding console counterparts (if the log method
* is supported by the current log level)
*/
var defaultLogHandler = function (instance, logType) {
var args = [];
for (var _i = 2; _i < arguments.length; _i++) {
args[_i - 2] = arguments[_i];
}
if (logType < instance.logLevel) {
return;
}
var now = new Date().toISOString();
var method = ConsoleMethod[logType];
if (method) {
console[method].apply(console, __spreadArray(["[" + now + "] " + instance.name + ":"], args));
}
else {
throw new Error("Attempted to log a message with an invalid logType (value: " + logType + ")");
}
};
var Logger = /** @class */ (function () {
/**
* 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
*/
function Logger(name) {
this.name = name;
/**
* The log level of the given Logger instance.
*/
this._logLevel = defaultLogLevel;
/**
* The main (internal) log handler for the Logger instance.
* Can be set to a new function in internal package code but not by user.
*/
this._logHandler = defaultLogHandler;
/**
* The optional, additional, user-defined log handler for the Logger instance.
*/
this._userLogHandler = null;
/**
* Capture the current instance for later use
*/
instances.push(this);
}
Object.defineProperty(Logger.prototype, "logLevel", {
get: function () {
return this._logLevel;
},
set: function (val) {
if (!(val in LogLevel)) {
throw new TypeError("Invalid value \"" + val + "\" assigned to `logLevel`");
}
this._logLevel = val;
},
enumerable: false,
configurable: true
});
// Workaround for setter/getter having to be the same type.
Logger.prototype.setLogLevel = function (val) {
this._logLevel = typeof val === 'string' ? levelStringToEnum[val] : val;
};
Object.defineProperty(Logger.prototype, "logHandler", {
get: function () {
return this._logHandler;
},
set: function (val) {
if (typeof val !== 'function') {
throw new TypeError('Value assigned to `logHandler` must be a function');
}
this._logHandler = val;
},
enumerable: false,
configurable: true
});
Object.defineProperty(Logger.prototype, "userLogHandler", {
get: function () {
return this._userLogHandler;
},
set: function (val) {
this._userLogHandler = val;
},
enumerable: false,
configurable: true
});
/**
* The functions below are all based on the `console` interface
*/
Logger.prototype.debug = function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
this._userLogHandler && this._userLogHandler.apply(this, __spreadArray([this, LogLevel.DEBUG], args));
this._logHandler.apply(this, __spreadArray([this, LogLevel.DEBUG], args));
};
Logger.prototype.log = function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
this._userLogHandler && this._userLogHandler.apply(this, __spreadArray([this, LogLevel.VERBOSE], args));
this._logHandler.apply(this, __spreadArray([this, LogLevel.VERBOSE], args));
};
Logger.prototype.info = function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
this._userLogHandler && this._userLogHandler.apply(this, __spreadArray([this, LogLevel.INFO], args));
this._logHandler.apply(this, __spreadArray([this, LogLevel.INFO], args));
};
Logger.prototype.warn = function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
this._userLogHandler && this._userLogHandler.apply(this, __spreadArray([this, LogLevel.WARN], args));
this._logHandler.apply(this, __spreadArray([this, LogLevel.WARN], args));
};
Logger.prototype.error = function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
this._userLogHandler && this._userLogHandler.apply(this, __spreadArray([this, LogLevel.ERROR], args));
this._logHandler.apply(this, __spreadArray([this, LogLevel.ERROR], args));
};
return Logger;
}());
function setLogLevel$1(level) {
instances.forEach(function (inst) {
inst.setLogLevel(level);
});
}
function setUserLogHandler(logCallback, options) {
var _loop_1 = function (instance) {
var customLogLevel = null;
if (options && options.level) {
customLogLevel = levelStringToEnum[options.level];
}
if (logCallback === null) {
instance.userLogHandler = null;
}
else {
instance.userLogHandler = function (instance, level) {
var args = [];
for (var _i = 2; _i < arguments.length; _i++) {
args[_i - 2] = arguments[_i];
}
var message = args
.map(function (arg) {
if (arg == null) {
return null;
}
else if (typeof arg === 'string') {
return arg;
}
else if (typeof arg === 'number' || typeof arg === 'boolean') {
return arg.toString();
}
else if (arg instanceof Error) {
return arg.message;
}
else {
try {
return JSON.stringify(arg);
}
catch (ignored) {
return null;
}
}
})
.filter(function (arg) { return arg; })
.join(' ');
if (level >= (customLogLevel !== null && customLogLevel !== void 0 ? customLogLevel : instance.logLevel)) {
logCallback({
level: LogLevel[level].toLowerCase(),
message: message,
args: args,
type: instance.name
});
}
};
}
};
for (var _i = 0, instances_1 = instances; _i < instances_1.length; _i++) {
var instance = instances_1[_i];
_loop_1(instance);
}
}
/**
* @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 === null || component === void 0 ? void 0 : component.type) === "VERSION" /* VERSION */;
}
const name$o = "https://www.gstatic.com/firebasejs/9.0.0/firebase-app.js";
const version$1 = "0.7.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.
*/
const logger = new Logger('https://www.gstatic.com/firebasejs/9.0.0/firebase-app.js');
const name$n = "https://www.gstatic.com/firebasejs/9.0.0/firebase-app.js-compat";
const name$m = "@firebase/analytics-compat";
const name$l = "@firebase/analytics";
const name$k = "https://www.gstatic.com/firebasejs/9.0.0/firebase-app.js-check-compat";
const name$j = "https://www.gstatic.com/firebasejs/9.0.0/firebase-app.js-check";
const name$i = "@firebase/auth";
const name$h = "@firebase/auth-compat";
const name$g = "@firebase/database";
const name$f = "@firebase/database-compat";
const name$e = "@firebase/functions";
const name$d = "@firebase/functions-compat";
const name$c = "@firebase/installations";
const name$b = "@firebase/installations-compat";
const name$a = "@firebase/messaging";
const name$9 = "@firebase/messaging-compat";
const name$8 = "@firebase/performance";
const name$7 = "@firebase/performance-compat";
const name$6 = "@firebase/remote-config";
const name$5 = "@firebase/remote-config-compat";
const name$4 = "@firebase/storage";
const name$3 = "@firebase/storage-compat";
const name$2 = "@firebase/firestore";
const name$1 = "@firebase/firestore-compat";
const name$p = "firebase";
const version$2 = "9.0.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$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$p]: '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();
/**
* 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);
}
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) {
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);
}
/**
* 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" /* NO_APP */]: "No Firebase App '{$appName}' has been created - " +
'call Firebase App.initializeApp()',
["bad-app-name" /* BAD_APP_NAME */]: "Illegal App name: '{$appName}",
["duplicate-app" /* DUPLICATE_APP */]: "Firebase App named '{$appName}' already exists with different options or config",
["app-deleted" /* APP_DELETED */]: "Firebase App named '{$appName}' already deleted",
["invalid-app-argument" /* INVALID_APP_ARGUMENT */]: 'firebase.{$appName}()