PageSourceSearch

https://daily.cat/firebase-messaging-sw.js

js daily.cat collected 2026-09-25 22:38:49 UTC 219,130 bytes, 5,251 lines download raw bytes

vendor: 17,124 bytes, lines 1-444
1(function () {
2    'use strict';
3
4    const getDefaultsFromPostinstall = () => (undefined);
5
6    /**
7     * @license
8     * Copyright 2017 Google LLC
9     *
10     * Licensed under the Apache License, Version 2.0 (the "License");
11     * you may not use this file except in compliance with the License.
12     * You may obtain a copy of the License at
13     *
14     *   http://www.apache.org/licenses/LICENSE-2.0
15     *
16     * Unless required by applicable law or agreed to in writing, software
17     * distributed under the License is distributed on an "AS IS" BASIS,
18     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19     * See the License for the specific language governing permissions and
20     * limitations under the License.
21     */
22    const stringToByteArray$1 = function (str) {
23        // TODO(user): Use native implementations if/when available
24        const out = [];
25        let p = 0;
26        for (let i = 0; i < str.length; i++) {
27            let c = str.charCodeAt(i);
28            if (c < 128) {
29                out[p++] = c;
30            }
31            else if (c < 2048) {
32                out[p++] = (c >> 6) | 192;
33                out[p++] = (c & 63) | 128;
34            }
35            else if ((c & 0xfc00) === 0xd800 &&
36                i + 1 < str.length &&
37                (str.charCodeAt(i + 1) & 0xfc00) === 0xdc00) {
38                // Surrogate Pair
39                c = 0x10000 + ((c & 0x03ff) << 10) + (str.charCodeAt(++i) & 0x03ff);
40                out[p++] = (c >> 18) | 240;
41                out[p++] = ((c >> 12) & 63) | 128;
42                out[p++] = ((c >> 6) & 63) | 128;
43                out[p++] = (c & 63) | 128;
44            }
45            else {
46                out[p++] = (c >> 12) | 224;
47                out[p++] = ((c >> 6) & 63) | 128;
48                out[p++] = (c & 63) | 128;
49            }
50        }
51        return out;
52    };
53    /**
54     * Turns an array of numbers into the string given by the concatenation of the
55     * characters to which the numbers correspond.
56     * @param bytes Array of numbers representing characters.
57     * @return Stringification of the array.
58     */
59    const byteArrayToString = function (bytes) {
60        // TODO(user): Use native implementations if/when available
61        const out = [];
62        let pos = 0, c = 0;
63        while (pos < bytes.length) {
64            const c1 = bytes[pos++];
65            if (c1 < 128) {
66                out[c++] = String.fromCharCode(c1);
67            }
68            else if (c1 > 191 && c1 < 224) {
69                const c2 = bytes[pos++];
70                out[c++] = String.fromCharCode(((c1 & 31) << 6) | (c2 & 63));
71            }
72            else if (c1 > 239 && c1 < 365) {
73                // Surrogate Pair
74                const c2 = bytes[pos++];
75                const c3 = bytes[pos++];
76                const c4 = bytes[pos++];
77                const u = (((c1 & 7) << 18) | ((c2 & 63) << 12) | ((c3 & 63) << 6) | (c4 & 63)) -
78                    0x10000;
79                out[c++] = String.fromCharCode(0xd800 + (u >> 10));
80                out[c++] = String.fromCharCode(0xdc00 + (u & 1023));
81            }
82            else {
83                const c2 = bytes[pos++];
84                const c3 = bytes[pos++];
85                out[c++] = String.fromCharCode(((c1 & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
86            }
87        }
88        return out.join('');
89    };
90    // We define it as an object literal instead of a class because a class compiled down to es5 can't
91    // be treeshaked. https://github.com/rollup/rollup/issues/1691
92    // Static lookup maps, lazily populated by init_()
93    // TODO(dlarocque): Define this as a class, since we no longer target ES5.
94    const base64 = {
95        /**
96         * Maps bytes to characters.
97         */
98        byteToCharMap_: null,
99        /**
100         * Maps characters to bytes.
101         */
102        charToByteMap_: null,
103        /**
104         * Maps bytes to websafe characters.
105         * @private
106         */
107        byteToCharMapWebSafe_: null,
108        /**
109         * Maps websafe characters to bytes.
110         * @private
111         */
112        charToByteMapWebSafe_: null,
113        /**
114         * Our default alphabet, shared between
115         * ENCODED_VALS and ENCODED_VALS_WEBSAFE
116         */
117        ENCODED_VALS_BASE: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' + 'abcdefghijklmnopqrstuvwxyz' + '0123456789',
118        /**
119         * Our default alphabet. Value 64 (=) is special; it means "nothing."
120         */
121        get ENCODED_VALS() {
122            return this.ENCODED_VALS_BASE + '+/=';
123        },
124        /**
125         * Our websafe alphabet.
126         */
127        get ENCODED_VALS_WEBSAFE() {
128            return this.ENCODED_VALS_BASE + '-_.';
129        },
130        /**
131         * Whether this browser supports the atob and btoa functions. This extension
132         * started at Mozilla but is now implemented by many browsers. We use the
133         * ASSUME_* variables to avoid pulling in the full useragent detection library
134         * but still allowing the standard per-browser compilations.
135         *
136         */
137        HAS_NATIVE_SUPPORT: typeof atob === 'function',
138        /**
139         * Base64-encode an array of bytes.
140         *
141         * @param input An array of bytes (numbers with
142         *     value in [0, 255]) to encode.
143         * @param webSafe Boolean indicating we should use the
144         *     alternative alphabet.
145         * @return The base64 encoded string.
146         */
147        encodeByteArray(input, webSafe) {
148            if (!Array.isArray(input)) {
149                throw Error('encodeByteArray takes an array as a parameter');
150            }
151            this.init_();
152            const byteToCharMap = webSafe
153                ? this.byteToCharMapWebSafe_
154                : this.byteToCharMap_;
155            const output = [];
156            for (let i = 0; i < input.length; i += 3) {
157                const byte1 = input[i];
158                const haveByte2 = i + 1 < input.length;
159                const byte2 = haveByte2 ? input[i + 1] : 0;
160                const haveByte3 = i + 2 < input.length;
161                const byte3 = haveByte3 ? input[i + 2] : 0;
162                const outByte1 = byte1 >> 2;
163                const outByte2 = ((byte1 & 0x03) << 4) | (byte2 >> 4);
164                let outByte3 = ((byte2 & 0x0f) << 2) | (byte3 >> 6);
165                let outByte4 = byte3 & 0x3f;
166                if (!haveByte3) {
167                    outByte4 = 64;
168                    if (!haveByte2) {
169                        outByte3 = 64;
170                    }
171                }
172                output.push(byteToCharMap[outByte1], byteToCharMap[outByte2], byteToCharMap[outByte3], byteToCharMap[outByte4]);
173            }
174            return output.join('');
175        },
176        /**
177         * Base64-encode a string.
178         *
179         * @param input A string to encode.
180         * @param webSafe If true, we should use the
181         *     alternative alphabet.
182         * @return The base64 encoded string.
183         */
184        encodeString(input, webSafe) {
185            // Shortcut for Mozilla browsers that implement
186            // a native base64 encoder in the form of "btoa/atob"
187            if (this.HAS_NATIVE_SUPPORT && !webSafe) {
188                return btoa(input);
189            }
190            return this.encodeByteArray(stringToByteArray$1(input), webSafe);
191        },
192        /**
193         * Base64-decode a string.
194         *
195         * @param input to decode.
196         * @param webSafe True if we should use the
197         *     alternative alphabet.
198         * @return string representing the decoded value.
199         */
200        decodeString(input, webSafe) {
201            // Shortcut for Mozilla browsers that implement
202            // a native base64 encoder in the form of "btoa/atob"
203            if (this.HAS_NATIVE_SUPPORT && !webSafe) {
204                return atob(input);
205            }
206            return byteArrayToString(this.decodeStringToByteArray(input, webSafe));
207        },
208        /**
209         * Base64-decode a string.
210         *
211         * In base-64 decoding, groups of four characters are converted into three
212         * bytes.  If the encoder did not apply padding, the input length may not
213         * be a multiple of 4.
214         *
215         * In this case, the last group will have fewer than 4 characters, and
216         * padding will be inferred.  If the group has one or two characters, it decodes
217         * to one byte.  If the group has three characters, it decodes to two bytes.
218         *
219         * @param input Input to decode.
220         * @param webSafe True if we should use the web-safe alphabet.
221         * @return bytes representing the decoded value.
222         */
223        decodeStringToByteArray(input, webSafe) {
224            this.init_();
225            const charToByteMap = webSafe
226                ? this.charToByteMapWebSafe_
227                : this.charToByteMap_;
228            const output = [];
229            for (let i = 0; i < input.length;) {
230                const byte1 = charToByteMap[input.charAt(i++)];
231                const haveByte2 = i < input.length;
232                const byte2 = haveByte2 ? charToByteMap[input.charAt(i)] : 0;
233                ++i;
234                const haveByte3 = i < input.length;
235                const byte3 = haveByte3 ? charToByteMap[input.charAt(i)] : 64;
236                ++i;
237                const haveByte4 = i < input.length;
238                const byte4 = haveByte4 ? charToByteMap[input.charAt(i)] : 64;
239                ++i;
240                if (byte1 == null || byte2 == null || byte3 == null || byte4 == null) {
241                    throw new DecodeBase64StringError();
242                }
243                const outByte1 = (byte1 << 2) | (byte2 >> 4);
244                output.push(outByte1);
245                if (byte3 !== 64) {
246                    const outByte2 = ((byte2 << 4) & 0xf0) | (byte3 >> 2);
247                    output.push(outByte2);
248                    if (byte4 !== 64) {
249                        const outByte3 = ((byte3 << 6) & 0xc0) | byte4;
250                        output.push(outByte3);
251                    }
252                }
253            }
254            return output;
255        },
256        /**
257         * Lazy static initialization function. Called before
258         * accessing any of the static map variables.
259         * @private
260         */
261        init_() {
262            if (!this.byteToCharMap_) {
263                this.byteToCharMap_ = {};
264                this.charToByteMap_ = {};
265                this.byteToCharMapWebSafe_ = {};
266                this.charToByteMapWebSafe_ = {};
267                // We want quick mappings back and forth, so we precompute two maps.
268                for (let i = 0; i < this.ENCODED_VALS.length; i++) {
269                    this.byteToCharMap_[i] = this.ENCODED_VALS.charAt(i);
270                    this.charToByteMap_[this.byteToCharMap_[i]] = i;
271                    this.byteToCharMapWebSafe_[i] = this.ENCODED_VALS_WEBSAFE.charAt(i);
272                    this.charToByteMapWebSafe_[this.byteToCharMapWebSafe_[i]] = i;
273                    // Be forgiving when decoding and correctly decode both encodings.
274                    if (i >= this.ENCODED_VALS_BASE.length) {
275                        this.charToByteMap_[this.ENCODED_VALS_WEBSAFE.charAt(i)] = i;
276                        this.charToByteMapWebSafe_[this.ENCODED_VALS.charAt(i)] = i;
277                    }
278                }
279            }
280        }
281    };
282    /**
283     * An error encountered while decoding base64 string.
284     */
285    class DecodeBase64StringError extends Error {
286        constructor() {
287            super(...arguments);
288            this.name = 'DecodeBase64StringError';
289        }
290    }
291    /**
292     * URL-safe base64 encoding
293     */
294    const base64Encode = function (str) {
295        const utf8Bytes = stringToByteArray$1(str);
296        return base64.encodeByteArray(utf8Bytes, true);
297    };
298    /**
299     * URL-safe base64 encoding (without "." padding in the end).
300     * e.g. Used in JSON Web Token (JWT) parts.
301     */
302    const base64urlEncodeWithoutPadding = function (str) {
303        // Use base64url encoding and remove padding in the end (dot characters).
304        return base64Encode(str).replace(/\./g, '');
305    };
306    /**
307     * URL-safe base64 decoding
308     *
309     * NOTE: DO NOT use the global atob() function - it does NOT support the
310     * base64Url variant encoding.
311     *
312     * @param str To be decoded
313     * @return Decoded result, if possible
314     */
315    const base64Decode = function (str) {
316        try {
317            return base64.decodeString(str, true);
318        }
319        catch (e) {
320            console.error('base64Decode failed: ', e);
321        }
322        return null;
323    };
324
325    /**
326     * @license
327     * Copyright 2022 Google LLC
328     *
329     * Licensed under the Apache License, Version 2.0 (the "License");
330     * you may not use this file except in compliance with the License.
331     * You may obtain a copy of the License at
332     *
333     *   http://www.apache.org/licenses/LICENSE-2.0
334     *
335     * Unless required by applicable law or agreed to in writing, software
336     * distributed under the License is distributed on an "AS IS" BASIS,
337     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
338     * See the License for the specific language governing permissions and
339     * limitations under the License.
340     */
341    /**
342     * Polyfill for `globalThis` object.
343     * @returns the `globalThis` object for the given environment.
344     * @public
345     */
346    function getGlobal() {
347        if (typeof self !== 'undefined') {
348            return self;
349        }
350        if (typeof window !== 'undefined') {
351            return window;
352        }
353        if (typeof global !== 'undefined') {
354            return global;
355        }
356        throw new Error('Unable to locate global object.');
357    }
358
359    /**
360     * @license
361     * Copyright 2022 Google LLC
362     *
363     * Licensed under the Apache License, Version 2.0 (the "License");
364     * you may not use this file except in compliance with the License.
365     * You may obtain a copy of the License at
366     *
367     *   http://www.apache.org/licenses/LICENSE-2.0
368     *
369     * Unless required by applicable law or agreed to in writing, software
370     * distributed under the License is distributed on an "AS IS" BASIS,
371     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
372     * See the License for the specific language governing permissions and
373     * limitations under the License.
374     */
375    const getDefaultsFromGlobal = () => getGlobal().__FIREBASE_DEFAULTS__;
376    /**
377     * Attempt to read defaults from a JSON string provided to
378     * process(.)env(.)__FIREBASE_DEFAULTS__ or a JSON file whose path is in
379     * process(.)env(.)__FIREBASE_DEFAULTS_PATH__
380     * The dots are in parens because certain compilers (Vite?) cannot
381     * handle seeing that variable in comments.
382     * See https://github.com/firebase/firebase-js-sdk/issues/6838
383     */
384    const getDefaultsFromEnvVariable = () => {
385        if (typeof process === 'undefined' || typeof process.env === 'undefined') {
386            return;
387        }
388        const defaultsJsonString = process.env.__FIREBASE_DEFAULTS__;
389        if (defaultsJsonString) {
390            return JSON.parse(defaultsJsonString);
391        }
392    };
393    const getDefaultsFromCookie = () => {
394        if (typeof document === 'undefined') {
395            return;
396        }
397        let match;
398        try {
399            match = document.cookie.match(/__FIREBASE_DEFAULTS__=([^;]+)/);
400        }
401        catch (e) {
402            // Some environments such as Angular Universal SSR have a
403            // `document` object but error on accessing `document.cookie`.
404            return;
405        }
406        const decoded = match && base64Decode(match[1]);
407        return decoded && JSON.parse(decoded);
408    };
409    /**
410     * Get the __FIREBASE_DEFAULTS__ object. It checks in order:
411     * (1) if such an object exists as a property of `globalThis`
412     * (2) if such an object was provided on a shell environment variable
413     * (3) if such an object exists in a cookie
414     * @public
415     */
416    const getDefaults = () => {
417        try {
418            return (getDefaultsFromPostinstall() ||
419                getDefaultsFromGlobal() ||
420                getDefaultsFromEnvVariable() ||
421                getDefaultsFromCookie());
422        }
423        catch (e) {
424            /**
425             * Catch-all for being unable to get __FIREBASE_DEFAULTS__ due
426             * to any environment case we have not accounted for. Log to
427             * info instead of swallowing so we can find these unknown cases
428             * and add paths for them if needed.
429             */
430            console.info(`Unable to get __FIREBASE_DEFAULTS__ due to: ${e}`);
431            return;
432        }
433    };
434    /**
435     * Returns Firebase app config stored in the __FIREBASE_DEFAULTS__ object.
436     * @public
437     */
438    const getDefaultAppConfig = () => getDefaults()?.config;
439
440    /**
441     * @license
442     * Copyright 2017 Google LLC
443     *
444     * Licensed under the Apache License, Version 2.0 (the "License");
445     * you may not use this file except in compliance with the License.
446     * You may obtain a copy of the License at
447     *
448     *   http://www.apache.org/licenses/LICENSE-2.0
449     *
450     * Unless required by applicable law or agreed to in writing, software
451     * distributed under the License is distributed on an "AS IS" BASIS,
452     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
453     * See the License for the specific language governing permissions and
454     * limitations under the License.
455     */
456    class Deferred {
457        constructor() {
458            this.reject = () => { };
459            this.resolve = () => { };
460            this.promise = new Promise((resolve, reject) => {
461                this.resolve = resolve;
462                this.reject = reject;
463            });
464        }
465        /**
466         * Our API internals are not promisified and cannot because our callback APIs have subtle expectations around
467         * invoking promises inline, which Promises are forbidden to do. This method accepts an optional node-style callback
468         * and returns a node-style callback which will resolve or reject the Deferred's promise.
469         */
470        wrapCallback(callback) {
471            return (error, value) => {
472                if (error) {
473                    this.reject(error);
474                }
475                else {
476                    this.resolve(value);
477                }
478                if (typeof callback === 'function') {
479                    // Attaching noop handler just in case developer wasn't expecting
480                    // promises
481                    this.promise.catch(() => { });
482                    // Some of our callbacks don't expect a value and our own tests
483                    // assert that the parameter length is 1
484                    if (callback.length === 1) {
485                        callback(error);
486                    }
487                    else {
488                        callback(error, value);
489                    }
490                }
491            };
492        }
493    }
494    /**
495     * This method checks if indexedDB is supported by current browser/service worker context
496     * @return true if indexedDB is supported by current browser/service worker context
497     */
498    function isIndexedDBAvailable() {
499        try {
500            return typeof indexedDB === 'object';
501        }
502        catch (e) {
503            return false;
504        }
505    }
506    /**
507     * This method validates browser/sw context for indexedDB by opening a dummy indexedDB database and reject
508     * if errors occur during the database open operation.
509     *
510     * @throws exception if current browser/sw context can't run idb.open (ex: Safari iframe, Firefox
511     * private browsing)
512     */
513    function validateIndexedDBOpenable() {
514        return new Promise((resolve, reject) => {
515            try {
516                let preExist = true;
517                const DB_CHECK_NAME = 'validate-browser-context-for-indexeddb-analytics-module';
518                const request = self.indexedDB.open(DB_CHECK_NAME);
519                request.onsuccess = () => {
520                    request.result.close();
521                    // delete database only when it doesn't pre-exist
522                    if (!preExist) {
523                        self.indexedDB.deleteDatabase(DB_CHECK_NAME);
524                    }
525                    resolve(true);
526                };
527                request.onupgradeneeded = () => {
528                    preExist = false;
529                };
530                request.onerror = () => {
531                    reject(request.error?.message || '');
532                };
533            }
534            catch (error) {
535                reject(error);
536            }
537        });
538    }
539
540    /**
541     * @license
542     * Copyright 2017 Google LLC
543     *
544     * Licensed under the Apache License, Version 2.0 (the "License");
545     * you may not use this file except in compliance with the License.
546     * You may obtain a copy of the License at
547     *
548     *   http://www.apache.org/licenses/LICENSE-2.0
549     *
550     * Unless required by applicable law or agreed to in writing, softw
550are
551     * distributed under the License is distributed on an "AS IS" BASIS,
552     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
553     * See the License for the specific language governing permissions and
554     * limitations under the License.
555     */
556    /**
557     * @fileoverview Standardized Firebase Error.
558     *
559     * Usage:
560     *
561     *   // TypeScript string literals for type-safe codes
562     *   type Err =
563     *     'unknown' |
564     *     'object-not-found'
565     *     ;
566     *
567     *   // Closure enum for type-safe error codes
568     *   // at-enum {string}
569     *   var Err = {
570     *     UNKNOWN: 'unknown',
571     *     OBJECT_NOT_FOUND: 'object-not-found',
572     *   }
573     *
574     *   let errors: Map<Err, string> = {
575     *     'generic-error': "Unknown error",
576     *     'file-not-found': "Could not find file: {$file}",
577     *   };
578     *
579     *   // Type-safe function - must pass a valid error code as param.
580     *   let error = new ErrorFactory<Err>('service', 'Service', errors);
581     *
582     *   ...
583     *   throw error.create(Err.GENERIC);
584     *   ...
585     *   throw error.create(Err.FILE_NOT_FOUND, {'file': fileName});
586     *   ...
587     *   // Service: Could not file file: foo.txt (service/file-not-found).
588     *
589     *   catch (e) {
590     *     assert(e.message === "Could not find file: foo.txt.");
591     *     if ((e as FirebaseError)?.code === 'service/file-not-found') {
592     *       console.log("Could not read file: " + e['file']);
593     *     }
594     *   }
595     */
596    const ERROR_NAME = 'FirebaseError';
597    // Based on code from:
598    // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error#Custom_Error_Types
599    class FirebaseError extends Error {
600        constructor(
601        /** The error code for this error. */
602        code, message, 
603        /** Custom data for this error. */
604        customData) {
605            super(message);
606            this.code = code;
607            this.customData = customData;
608            /** The custom name for all FirebaseErrors. */
609            this.name = ERROR_NAME;
610            // Fix For ES5
611            // https://github.com/Microsoft/TypeScript-wiki/blob/master/Breaking-Changes.md#extending-built-ins-like-error-array-and-map-may-no-longer-work
612            // TODO(dlarocque): Replace this with `new.target`: https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-2.html#support-for-newtarget
613            //                   which we can now use since we no longer target ES5.
614            Object.setPrototypeOf(this, FirebaseError.prototype);
615            // Maintains proper stack trace for where our error was thrown.
616            // Only available on V8.
617            if (Error.captureStackTrace) {
618                Error.captureStackTrace(this, ErrorFactory.prototype.create);
619            }
620        }
621    }
622    class ErrorFactory {
623        constructor(service, serviceName, errors) {
624            this.service = service;
625            this.serviceName = serviceName;
626            this.errors = errors;
627        }
628        create(code, ...data) {
629            const customData = data[0] || {};
630            const fullCode = `${this.service}/${code}`;
631            const template = this.errors[code];
632            const message = template ? replaceTemplate(template, customData) : 'Error';
633            // Service Name: Error message (service/code).
634            const fullMessage = `${this.serviceName}: ${message} (${fullCode}).`;
635            const error = new FirebaseError(fullCode, fullMessage, customData);
636            return error;
637        }
638    }
639    function replaceTemplate(template, data) {
640        return template.replace(PATTERN, (_, key) => {
641            const value = data[key];
642            return value != null ? String(value) : `<${key}?>`;
643        });
644    }
645    const PATTERN = /\{\$([^}]+)}/g;
646    /**
647     * Deep equal two objects. Support Arrays and Objects.
648     */
649    function deepEqual(a, b) {
650        if (a === b) {
651            return true;
652        }
653        const aKeys = Object.keys(a);
654        const bKeys = Object.keys(b);
655        for (const k of aKeys) {
656            if (!bKeys.includes(k)) {
657                return false;
vendor: 16,596 bytes, lines 658-1045
658            }
659            const aProp = a[k];
660            const bProp = b[k];
661            if (isObject(aProp) && isObject(bProp)) {
662                if (!deepEqual(aProp, bProp)) {
663                    return false;
664                }
665            }
666            else if (aProp !== bProp) {
667                return false;
668            }
669        }
670        for (const k of bKeys) {
671            if (!aKeys.includes(k)) {
672                return false;
673            }
674        }
675        return true;
676    }
677    function isObject(thing) {
678        return thing !== null && typeof thing === 'object';
679    }
680
681    /**
682     * @license
683     * Copyright 2021 Google LLC
684     *
685     * Licensed under the Apache License, Version 2.0 (the "License");
686     * you may not use this file except in compliance with the License.
687     * You may obtain a copy of the License at
688     *
689     *   http://www.apache.org/licenses/LICENSE-2.0
690     *
691     * Unless required by applicable law or agreed to in writing, software
692     * distributed under the License is distributed on an "AS IS" BASIS,
693     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
694     * See the License for the specific language governing permissions and
695     * limitations under the License.
696     */
697    function getModularInstance(service) {
698        if (service && service._delegate) {
699            return service._delegate;
700        }
701        else {
702            return service;
703        }
704    }
705
706    /**
707     * Component for service name T, e.g. `auth`, `auth-internal`
708     */
709    class Component {
710        /**
711         *
712         * @param name The public service name, e.g. app, auth, firestore, database
713         * @param instanceFactory Service factory responsible for creating the public interface
714         * @param type whether the service provided by the component is public or private
715         */
716        constructor(name, instanceFactory, type) {
717            this.name = name;
718            this.instanceFactory = instanceFactory;
719            this.type = type;
720            this.multipleInstances = false;
721            /**
722             * Properties to be added to the service namespace
723             */
724            this.serviceProps = {};
725            this.instantiationMode = "LAZY" /* InstantiationMode.LAZY */;
726            this.onInstanceCreated = null;
727        }
728        setInstantiationMode(mode) {
729            this.instantiationMode = mode;
730            return this;
731        }
732        setMultipleInstances(multipleInstances) {
733            this.multipleInstances = multipleInstances;
734            return this;
735        }
736        setServiceProps(props) {
737            this.serviceProps = props;
738            return this;
739        }
740        setInstanceCreatedCallback(callback) {
741            this.onInstanceCreated = callback;
742            return this;
743        }
744    }
745
746    /**
747     * @license
748     * Copyright 2019 Google LLC
749     *
750     * Licensed under the Apache License, Version 2.0 (the "License");
751     * you may not use this file except in compliance with the License.
752     * You may obtain a copy of the License at
753     *
754     *   http://www.apache.org/licenses/LICENSE-2.0
755     *
756     * Unless required by applicable law or agreed to in writing, software
757     * distributed under the License is distributed on an "AS IS" BASIS,
758     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
759     * See the License for the specific language governing permissions and
760     * limitations under the License.
761     */
762    const DEFAULT_ENTRY_NAME$1 = '[DEFAULT]';
763
764    /**
765     * @license
766     * Copyright 2019 Google LLC
767     *
768     * Licensed under the Apache License, Version 2.0 (the "License");
769     * you may not use this file except in compliance with the License.
770     * You may obtain a copy of the License at
771     *
772     *   http://www.apache.org/licenses/LICENSE-2.0
773     *
774     * Unless required by applicable law or agreed to in writing, software
775     * distributed under the License is distributed on an "AS IS" BASIS,
776     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
777     * See the License for the specific language governing permissions and
778     * limitations under the License.
779     */
780    /**
781     * Provider for instance for service name T, e.g. 'auth', 'auth-internal'
782     * NameServiceMapping[T] is an alias for the type of the instance
783     */
784    class Provider {
785        constructor(name, container) {
786            this.name = name;
787            this.container = container;
788            this.component = null;
789            this.instances = new Map();
790            this.instancesDeferred = new Map();
791            this.instancesOptions = new Map();
792            this.onInitCallbacks = new Map();
793        }
794        /**
795         * @param identifier A provider can provide multiple instances of a service
796         * if this.component.multipleInstances is true.
797         */
798        get(identifier) {
799            // if multipleInstances is not supported, use the default name
800            const normalizedIdentifier = this.normalizeInstanceIdentifier(identifier);
801            if (!this.instancesDeferred.has(normalizedIdentifier)) {
802                const deferred = new Deferred();
803                this.instancesDeferred.set(normalizedIdentifier, deferred);
804                if (this.isInitialized(normalizedIdentifier) ||
805                    this.shouldAutoInitialize()) {
806                    // initialize the service if it can be auto-initialized
807                    try {
808                        const instance = this.getOrInitializeService({
809                            instanceIdentifier: normalizedIdentifier
810                        });
811                        if (instance) {
812                            deferred.resolve(instance);
813                        }
814                    }
815                    catch (e) {
816                        // when the instance factory throws an exception during get(), it should not cause
817                        // a fatal error. We just return the unresolved promise in this case.
818                    }
819                }
820            }
821            return this.instancesDeferred.get(normalizedIdentifier).promise;
822        }
823        getImmediate(options) {
824            // if multipleInstances is not supported, use the default name
825            const normalizedIdentifier = this.normalizeInstanceIdentifier(options?.identifier);
826            const optional = options?.optional ?? false;
827            if (this.isInitialized(normalizedIdentifier) ||
828                this.shouldAutoInitialize()) {
829                try {
830                    return this.getOrInitializeService({
831                        instanceIdentifier: normalizedIdentifier
832                    });
833                }
834                catch (e) {
835                    if (optional) {
836                        return null;
837                    }
838                    else {
839                        throw e;
840                    }
841                }
842            }
843            else {
844                // In case a component is not initialized and should/cannot be auto-initialized at the moment, return null if the optional flag is set, or throw
845                if (optional) {
846                    return null;
847                }
848                else {
849                    throw Error(`Service ${this.name} is not available`);
850                }
851            }
852        }
853        getComponent() {
854            return this.component;
855        }
856        setComponent(component) {
857            if (component.name !== this.name) {
858                throw Error(`Mismatching Component ${component.name} for Provider ${this.name}.`);
859            }
860            if (this.component) {
861                throw Error(`Component for ${this.name} has already been provided`);
862            }
863            this.component = component;
864            // return early without attempting to initialize the component if the component requires explicit initialization (calling `Provider.initialize()`)
865            if (!this.shouldAutoInitialize()) {
866                return;
867            }
868            // if the service is eager, initialize the default instance
869            if (isComponentEager(component)) {
870                try {
871                    this.getOrInitializeService({ instanceIdentifier: DEFAULT_ENTRY_NAME$1 });
872                }
873                catch (e) {
874                    // when the instance factory for an eager Component throws an exception during the eager
875                    // initialization, it should not cause a fatal error.
876                    // TODO: Investigate if we need to make it configurable, because some component may want to cause
877                    // a fatal error in this case?
878                }
879            }
880            // Create service instances for the pending promises and resolve them
881            // NOTE: if this.multipleInstances is false, only the default instance will be created
882            // and all promises with resolve with it regardless of the identifier.
883            for (const [instanceIdentifier, instanceDeferred] of this.instancesDeferred.entries()) {
884                const normalizedIdentifier = this.normalizeInstanceIdentifier(instanceIdentifier);
885                try {
886                    // `getOrInitializeService()` should always return a valid instance since a component is guaranteed. use ! to make typescript happy.
887                    const instance = this.getOrInitializeService({
888                        instanceIdentifier: normalizedIdentifier
889                    });
890                    instanceDeferred.resolve(instance);
891                }
892                catch (e) {
893                    // when the instance factory throws an exception, it should not cause
894                    // a fatal error. We just leave the promise unresolved.
895                }
896            }
897        }
898        clearInstance(identifier = DEFAULT_ENTRY_NAME$1) {
899            this.instancesDeferred.delete(identifier);
900            this.instancesOptions.delete(identifier);
901            this.instances.delete(identifier);
902        }
903        // app.delete() will call this method on every provider to delete the services
904        // TODO: should we mark the provider as deleted?
905        async delete() {
906            const services = Array.from(this.instances.values());
907            await Promise.all([
908                ...services
909                    .filter(service => 'INTERNAL' in service) // legacy services
910                    // eslint-disable-next-line @typescript-eslint/no-explicit-any
911                    .map(service => service.INTERNAL.delete()),
912                ...services
913                    .filter(service => '_delete' in service) // modularized services
914                    // eslint-disable-next-line @typescript-eslint/no-explicit-any
915                    .map(service => service._delete())
916            ]);
917        }
918        isComponentSet() {
919            return this.component != null;
920        }
921        isInitialized(identifier = DEFAULT_ENTRY_NAME$1) {
922            return this.instances.has(identifier);
923        }
924        getOptions(identifier = DEFAULT_ENTRY_NAME$1) {
925            return this.instancesOptions.get(identifier) || {};
926        }
927        initialize(opts = {}) {
928            const { options = {} } = opts;
929            const normalizedIdentifier = this.normalizeInstanceIdentifier(opts.instanceIdentifier);
930            if (this.isInitialized(normalizedIdentifier)) {
931                throw Error(`${this.name}(${normalizedIdentifier}) has already been initialized`);
932            }
933            if (!this.isComponentSet()) {
934                throw Error(`Component ${this.name} has not been registered yet`);
935            }
936            const instance = this.getOrInitializeService({
937                instanceIdentifier: normalizedIdentifier,
938                options
939            });
940            // resolve any pending promise waiting for the service instance
941            for (const [instanceIdentifier, instanceDeferred] of this.instancesDeferred.entries()) {
942                const normalizedDeferredIdentifier = this.normalizeInstanceIdentifier(instanceIdentifier);
943                if (normalizedIdentifier === normalizedDeferredIdentifier) {
944                    instanceDeferred.resolve(instance);
945                }
946            }
947            return instance;
948        }
949        /**
950         *
951         * @param callback - a function that will be invoked  after the provider has been initialized by calling provider.initialize().
952         * The function is invoked SYNCHRONOUSLY, so it should not execute any longrunning tasks in order to not block the program.
953         *
954         * @param identifier An optional instance identifier
955         * @returns a function to unregister the callback
956         */
957        onInit(callback, identifier) {
958            const normalizedIdentifier = this.normalizeInstanceIdentifier(identifier);
959            const existingCallbacks = this.onInitCallbacks.get(normalizedIdentifier) ??
960                new Set();
961            existingCallbacks.add(callback);
962            this.onInitCallbacks.set(normalizedIdentifier, existingCallbacks);
963            const existingInstance = this.instances.get(normalizedIdentifier);
964            if (existingInstance) {
965                callback(existingInstance, normalizedIdentifier);
966            }
967            return () => {
968                existingCallbacks.delete(callback);
969            };
970        }
971        /**
972         * Invoke onInit callbacks synchronously
973         * @param instance the service instance`
974         */
975        invokeOnInitCallbacks(instance, identifier) {
976            const callbacks = this.onInitCallbacks.get(identifier);
977            if (!callbacks) {
978                return;
979            }
980            for (const callback of callbacks) {
981                try {
982                    callback(instance, identifier);
983                }
984                catch {
985                    // ignore errors in the onInit callback
986                }
987            }
988        }
989        getOrInitializeService({ instanceIdentifier, options = {} }) {
990            let instance = this.instances.get(instanceIdentifier);
991            if (!instance && this.component) {
992                instance = this.component.instanceFactory(this.container, {
993                    instanceIdentifier: normalizeIdentifierForFactory(instanceIdentifier),
994                    options
995                });
996                this.instances.set(instanceIdentifier, instance);
997                this.instancesOptions.set(instanceIdentifier, options);
998                /**
999                 * Invoke onInit listeners.
1000                 * Note this.component.onInstanceCreated is different, which is used by the component creator,
1001                 * while onInit listeners are registered by consumers of the provider.
1002                 */
1003                this.invokeOnInitCallbacks(instance, instanceIdentifier);
1004                /**
1005                 * Order is important
1006                 * onInstanceCreated() should be called after this.instances.set(instanceIdentifier, instance); which
1007                 * makes `isInitialized()` return true.
1008                 */
1009                if (this.component.onInstanceCreated) {
1010                    try {
1011                        this.component.onInstanceCreated(this.container, instanceIdentifier, instance);
1012                    }
1013                    catch {
1014                        // ignore errors in the onInstanceCreatedCallback
1015                    }
1016                }
1017            }
1018            return instance || null;
1019        }
1020        normalizeInstanceIdentifier(identifier = DEFAULT_ENTRY_NAME$1) {
1021            if (this.component) {
1022                return this.component.multipleInstances ? identifier : DEFAULT_ENTRY_NAME$1;
1023            }
1024            else {
1025                return identifier; // assume multiple instances are supported before the component is provided.
1026            }
1027        }
1028        shouldAutoInitialize() {
1029            return (!!this.component &&
1030                this.component.instantiationMode !== "EXPLICIT" /* InstantiationMode.EXPLICIT */);
1031        }
1032    }
1033    // undefined should be passed to the service factory for the default instance
1034    function normalizeIdentifierForFactory(identifier) {
1035        return identifier === DEFAULT_ENTRY_NAME$1 ? undefined : identifier;
1036    }
1037    function isComponentEager(component) {
1038        return component.instantiationMode === "EAGER" /* InstantiationMode.EAGER */;
1039    }
1040
1041    /**
1042     * @license
1043     * Copyright 2019 Google LLC
1044     *
1045     * Licensed under the Apache License, Version 2.0 (the "License");
1046     * you may not use this file except in compliance with the License.
1047     * You may obtain a copy of the License at
1048     *
1049     *   http://www.apache.org/licenses/LICENSE-2.0
1050     *
1051     * Unless required by applicable law or agreed to in writing, software
1052     * distributed under the License is distributed on an "AS IS" BASIS,
1053     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1054     * See the License for the specific language governing permissions and
1055     * limitations under the License.
1056     */
1057    /**
1058     * ComponentContainer that provides Providers for service name T, e.g. `auth`, `auth-internal`
1059     */
1060    class ComponentContainer {
1061        constructor(name) {
1062            this.name = name;
1063            this.providers = new Map();
1064        }
1065        /**
1066         *
1067         * @param component Component being added
1068         * @param overwrite When a component with the same name has already been registered,
1069         * if overwrite is true: overwrite the existing component with the new component and create a new
1070         * provider with the new component. It can be useful in tests where you want to use different mocks
1071         * for different tests.
1072         * if overwrite is false: throw an exception
1073         */
1074        addComponent(component) {
1075            const provider = this.getProvider(component.name);
1076            if (provider.isComponentSet()) {
1077                throw new Error(`Component ${component.name} has already been registered with ${this.name}`);
1078            }
1079            provider.setComponent(component);
1080        }
1081        addOrOverwriteComponent(component) {
1082            const provider = this.getProvider(component.name);
1083            if (provider.isComponentSet()) {
1084                // delete the existing provider from the container, so we can register the new component
1085                this.providers.delete(component.name);
1086            }
1087            this.addComponent(component);
1088        }
1089        /**
1090         * getProvider provides a type safe interface where it can only be called with a field name
1091         * present in NameServiceMapping interface.
1092         *
1093         * Firebase SDKs providing services should extend NameServiceMapping interface to register
1094         * themselves.
1095         */
1096        getProvider(name) {
1097            if (this.providers.has(name)) {
1098                return this.providers.get(name);
1099            }
1100            // create a Provider for a service that hasn't registered with Firebase
1101            const provider = new Provider(name, this);
1102            this.providers.set(name, provider);
1103            return provider;
1104        }
1105        getProviders() {
1106            return Array.from(this.providers.values());
1107        }
1108    }
1109
1110    /**
1111     * @license
1112     * Copyright 2017 Google LLC
1113     *
1114     * Licensed under the Apache License, Version 2.0 (the "License");
1115     * you may not use this file except in compliance with the License.
1116     * You may obtain a copy of the License at
1117     *
1118     *   http://www.apache.org/licenses/LICENSE-2.0
1119     *
1120     * Unless required by applicable law or agreed to in writing, software
1121     * distributed under the License is distributed on an "AS IS" BASIS,
1122     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1123     * See the License for the specific language governing permissions and
1124     * limitations under the License.
1125     */
1126    /**
1127     * A container for all of the Logger instances
1128     */
1129    /**
1130     * The JS SDK supports 5 log levels and also allows a user the ability to
1131     * silence the logs altogether.
1132     *
1133     * The order is a follows:
1134     * DEBUG < VERBOSE < INFO < WARN < ERROR
1135     *
1136     * All of the log types above the current log level will be captured (i.e. if
1137     * you set the log level to `INFO`, errors will still be logged, but `DEBUG` and
1138     * `VERBOSE` logs will not)
1139     */
1140    var LogLevel;
1141    (function (LogLevel) {
1142        LogLevel[LogLevel["DEBUG"] = 0] = "DEBUG";
1143        LogLevel[LogLevel["VERBOSE"] = 1] = "VERBOSE";
1144        LogLevel[LogLevel["INFO"] = 2] = "INFO";
1145        LogLevel[LogLevel["WARN"] = 3] = "WARN";
vendor: 10,109 bytes, lines 1146-1403
1146        LogLevel[LogLevel["ERROR"] = 4] = "ERROR";
1147        LogLevel[LogLevel["SILENT"] = 5] = "SILENT";
1148    })(LogLevel || (LogLevel = {}));
1149    const levelStringToEnum = {
1150        'debug': LogLevel.DEBUG,
1151        'verbose': LogLevel.VERBOSE,
1152        'info': LogLevel.INFO,
1153        'warn': LogLevel.WARN,
1154        'error': LogLevel.ERROR,
1155        'silent': LogLevel.SILENT
1156    };
1157    /**
1158     * The default log level
1159     */
1160    const defaultLogLevel = LogLevel.INFO;
1161    /**
1162     * By default, `console.debug` is not displayed in the developer console (in
1163     * chrome). To avoid forcing users to have to opt-in to these logs twice
1164     * (i.e. once for firebase, and once in the console), we are sending `DEBUG`
1165     * logs to the `console.log` function.
1166     */
1167    const ConsoleMethod = {
1168        [LogLevel.DEBUG]: 'log',
1169        [LogLevel.VERBOSE]: 'log',
1170        [LogLevel.INFO]: 'info',
1171        [LogLevel.WARN]: 'warn',
1172        [LogLevel.ERROR]: 'error'
1173    };
1174    /**
1175     * The default log handler will forward DEBUG, VERBOSE, INFO, WARN, and ERROR
1176     * messages on to their corresponding console counterparts (if the log method
1177     * is supported by the current log level)
1178     */
1179    const defaultLogHandler = (instance, logType, ...args) => {
1180        if (logType < instance.logLevel) {
1181            return;
1182        }
1183        const now = new Date().toISOString();
1184        const method = ConsoleMethod[logType];
1185        if (method) {
1186            console[method](`[${now}]  ${instance.name}:`, ...args);
1187        }
1188        else {
1189            throw new Error(`Attempted to log a message with an invalid logType (value: ${logType})`);
1190        }
1191    };
1192    class Logger {
1193        /**
1194         * Gives you an instance of a Logger to capture messages according to
1195         * Firebase's logging scheme.
1196         *
1197         * @param name The name that the logs will be associated with
1198         */
1199        constructor(name) {
1200            this.name = name;
1201            /**
1202             * The log level of the given Logger instance.
1203             */
1204            this._logLevel = defaultLogLevel;
1205            /**
1206             * The main (internal) log handler for the Logger instance.
1207             * Can be set to a new function in internal package code but not by user.
1208             */
1209            this._logHandler = defaultLogHandler;
1210            /**
1211             * The optional, additional, user-defined log handler for the Logger instance.
1212             */
1213            this._userLogHandler = null;
1214        }
1215        get logLevel() {
1216            return this._logLevel;
1217        }
1218        set logLevel(val) {
1219            if (!(val in LogLevel)) {
1220                throw new TypeError(`Invalid value "${val}" assigned to \`logLevel\``);
1221            }
1222            this._logLevel = val;
1223        }
1224        // Workaround for setter/getter having to be the same type.
1225        setLogLevel(val) {
1226            this._logLevel = typeof val === 'string' ? levelStringToEnum[val] : val;
1227        }
1228        get logHandler() {
1229            return this._logHandler;
1230        }
1231        set logHandler(val) {
1232            if (typeof val !== 'function') {
1233                throw new TypeError('Value assigned to `logHandler` must be a function');
1234            }
1235            this._logHandler = val;
1236        }
1237        get userLogHandler() {
1238            return this._userLogHandler;
1239        }
1240        set userLogHandler(val) {
1241            this._userLogHandler = val;
1242        }
1243        /**
1244         * The functions below are all based on the `console` interface
1245         */
1246        debug(...args) {
1247            this._userLogHandler && this._userLogHandler(this, LogLevel.DEBUG, ...args);
1248            this._logHandler(this, LogLevel.DEBUG, ...args);
1249        }
1250        log(...args) {
1251            this._userLogHandler &&
1252                this._userLogHandler(this, LogLevel.VERBOSE, ...args);
1253            this._logHandler(this, LogLevel.VERBOSE, ...args);
1254        }
1255        info(...args) {
1256            this._userLogHandler && this._userLogHandler(this, LogLevel.INFO, ...args);
1257            this._logHandler(this, LogLevel.INFO, ...args);
1258        }
1259        warn(...args) {
1260            this._userLogHandler && this._userLogHandler(this, LogLevel.WARN, ...args);
1261            this._logHandler(this, LogLevel.WARN, ...args);
1262        }
1263        error(...args) {
1264            this._userLogHandler && this._userLogHandler(this, LogLevel.ERROR, ...args);
1265            this._logHandler(this, LogLevel.ERROR, ...args);
1266        }
1267    }
1268
1269    const instanceOfAny = (object, constructors) => constructors.some((c) => object instanceof c);
1270
1271    let idbProxyableTypes;
1272    let cursorAdvanceMethods;
1273    // This is a function to prevent it throwing up in node environments.
1274    function getIdbProxyableTypes() {
1275        return (idbProxyableTypes ||
1276            (idbProxyableTypes = [
1277                IDBDatabase,
1278                IDBObjectStore,
1279                IDBIndex,
1280                IDBCursor,
1281                IDBTransaction,
1282            ]));
1283    }
1284    // This is a function to prevent it throwing up in node environments.
1285    function getCursorAdvanceMethods() {
1286        return (cursorAdvanceMethods ||
1287            (cursorAdvanceMethods = [
1288                IDBCursor.prototype.advance,
1289                IDBCursor.prototype.continue,
1290                IDBCursor.prototype.continuePrimaryKey,
1291            ]));
1292    }
1293    const cursorRequestMap = new WeakMap();
1294    const transactionDoneMap = new WeakMap();
1295    const transactionStoreNamesMap = new WeakMap();
1296    const transformCache = new WeakMap();
1297    const reverseTransformCache = new WeakMap();
1298    function promisifyRequest(request) {
1299        const promise = new Promise((resolve, reject) => {
1300            const unlisten = () => {
1301                request.removeEventListener('success', success);
1302                request.removeEventListener('error', error);
1303            };
1304            const success = () => {
1305                resolve(wrap(request.result));
1306                unlisten();
1307            };
1308            const error = () => {
1309                reject(request.error);
1310                unlisten();
1311            };
1312            request.addEventListener('success', success);
1313            request.addEventListener('error', error);
1314        });
1315        promise
1316            .then((value) => {
1317            // Since cursoring reuses the IDBRequest (*sigh*), we cache it for later retrieval
1318            // (see wrapFunction).
1319            if (value instanceof IDBCursor) {
1320                cursorRequestMap.set(value, request);
1321            }
1322            // Catching to avoid "Uncaught Promise exceptions"
1323        })
1324            .catch(() => { });
1325        // This mapping exists in reverseTransformCache but doesn't doesn't exist in transformCache. This
1326        // is because we create many promises from a single IDBRequest.
1327        reverseTransformCache.set(promise, request);
1328        return promise;
1329    }
1330    function cacheDonePromiseForTransaction(tx) {
1331        // Early bail if we've already created a done promise for this transaction.
1332        if (transactionDoneMap.has(tx))
1333            return;
1334        const done = new Promise((resolve, reject) => {
1335            const unlisten = () => {
1336                tx.removeEventListener('complete', complete);
1337                tx.removeEventListener('error', error);
1338                tx.removeEventListener('abort', error);
1339            };
1340            const complete = () => {
1341                resolve();
1342                unlisten();
1343            };
1344            const error = () => {
1345                reject(tx.error || new DOMException('AbortError', 'AbortError'));
1346                unlisten();
1347            };
1348            tx.addEventListener('complete', complete);
1349            tx.addEventListener('error', error);
1350            tx.addEventListener('abort', error);
1351        });
1352        // Cache it for later retrieval.
1353        transactionDoneMap.set(tx, done);
1354    }
1355    let idbProxyTraps = {
1356        get(target, prop, receiver) {
1357            if (target instanceof IDBTransaction) {
1358                // Special handling for transaction.done.
1359                if (prop === 'done')
1360                    return transactionDoneMap.get(target);
1361                // Polyfill for objectStoreNames because of Edge.
1362                if (prop === 'objectStoreNames') {
1363                    return target.objectStoreNames || transactionStoreNamesMap.get(target);
1364                }
1365                // Make tx.store return the only store in the transaction, or undefined if there are many.
1366                if (prop === 'store') {
1367                    return receiver.objectStoreNames[1]
1368                        ? undefined
1369                        : receiver.objectStore(receiver.objectStoreNames[0]);
1370                }
1371            }
1372            // Else transform whatever we get back.
1373            return wrap(target[prop]);
1374        },
1375        set(target, prop, value) {
1376            target[prop] = value;
1377            return true;
1378        },
1379        has(target, prop) {
1380            if (target instanceof IDBTransaction &&
1381                (prop === 'done' || prop === 'store')) {
1382                return true;
1383            }
1384            return prop in target;
1385        },
1386    };
1387    function replaceTraps(callback) {
1388        idbProxyTraps = callback(idbProxyTraps);
1389    }
1390    function wrapFunction(func) {
1391        // Due to expected object equality (which is enforced by the caching in `wrap`), we
1392        // only create one new func per func.
1393        // Edge doesn't support objectStoreNames (booo), so we polyfill it here.
1394        if (func === IDBDatabase.prototype.transaction &&
1395            !('objectStoreNames' in IDBTransaction.prototype)) {
1396            return function (storeNames, ...args) {
1397                const tx = func.call(unwrap(this), storeNames, ...args);
1398                transactionStoreNamesMap.set(tx, storeNames.sort ? storeNames.sort() : [storeNames]);
1399                return wrap(tx);
1400            };
1401        }
1402        // Cursor methods are special, as the behaviour is a little more different to standard IDB. In
1403        // IDB, you advance the cursor and wait for a new 'success' on the ID
vendor: 6,353 bytes, lines 1403-1548
1403BRequest that gave you the
1404        // cursor. It's kinda like a promise that can resolve with many values. That doesn't make sense
1405        // with real promises, so each advance methods returns a new promise for the cursor object, or
1406        // undefined if the end of the cursor has been reached.
1407        if (getCursorAdvanceMethods().includes(func)) {
1408            return function (...args) {
1409                // Calling the original function with the proxy as 'this' causes ILLEGAL INVOCATION, so we use
1410                // the original object.
1411                func.apply(unwrap(this), args);
1412                return wrap(cursorRequestMap.get(this));
1413            };
1414        }
1415        return function (...args) {
1416            // Calling the original function with the proxy as 'this' causes ILLEGAL INVOCATION, so we use
1417            // the original object.
1418            return wrap(func.apply(unwrap(this), args));
1419        };
1420    }
1421    function transformCachableValue(value) {
1422        if (typeof value === 'function')
1423            return wrapFunction(value);
1424        // This doesn't return, it just creates a 'done' promise for the transaction,
1425        // which is later returned for transaction.done (see idbObjectHandler).
1426        if (value instanceof IDBTransaction)
1427            cacheDonePromiseForTransaction(value);
1428        if (instanceOfAny(value, getIdbProxyableTypes()))
1429            return new Proxy(value, idbProxyTraps);
1430        // Return the same value back if we're not going to transform it.
1431        return value;
1432    }
1433    function wrap(value) {
1434        // We sometimes generate multiple promises from a single IDBRequest (eg when cursoring), because
1435        // IDB is weird and a single IDBRequest can yield many responses, so these can't be cached.
1436        if (value instanceof IDBRequest)
1437            return promisifyRequest(value);
1438        // If we've already transformed this value before, reuse the transformed value.
1439        // This is faster, but it also provides object equality.
1440        if (transformCache.has(value))
1441            return transformCache.get(value);
1442        const newValue = transformCachableValue(value);
1443        // Not all types are transformed.
1444        // These may be primitive types, so they can't be WeakMap keys.
1445        if (newValue !== value) {
1446            transformCache.set(value, newValue);
1447            reverseTransformCache.set(newValue, value);
1448        }
1449        return newValue;
1450    }
1451    const unwrap = (value) => reverseTransformCache.get(value);
1452
1453    /**
1454     * Open a database.
1455     *
1456     * @param name Name of the database.
1457     * @param version Schema version.
1458     * @param callbacks Additional callbacks.
1459     */
1460    function openDB(name, version, { blocked, upgrade, blocking, terminated } = {}) {
1461        const request = indexedDB.open(name, version);
1462        const openPromise = wrap(request);
1463        if (upgrade) {
1464            request.addEventListener('upgradeneeded', (event) => {
1465                upgrade(wrap(request.result), event.oldVersion, event.newVersion, wrap(request.transaction), event);
1466            });
1467        }
1468        if (blocked) {
1469            request.addEventListener('blocked', (event) => blocked(
1470            // Casting due to https://github.com/microsoft/TypeScript-DOM-lib-generator/pull/1405
1471            event.oldVersion, event.newVersion, event));
1472        }
1473        openPromise
1474            .then((db) => {
1475            if (terminated)
1476                db.addEventListener('close', () => terminated());
1477            if (blocking) {
1478                db.addEventListener('versionchange', (event) => blocking(event.oldVersion, event.newVersion, event));
1479            }
1480        })
1481            .catch(() => { });
1482        return openPromise;
1483    }
1484    /**
1485     * Delete a database.
1486     *
1487     * @param name Name of the database.
1488     */
1489    function deleteDB(name, { blocked } = {}) {
1490        const request = indexedDB.deleteDatabase(name);
1491        if (blocked) {
1492            request.addEventListener('blocked', (event) => blocked(
1493            // Casting due to https://github.com/microsoft/TypeScript-DOM-lib-generator/pull/1405
1494            event.oldVersion, event));
1495        }
1496        return wrap(request).then(() => undefined);
1497    }
1498
1499    const readMethods = ['get', 'getKey', 'getAll', 'getAllKeys', 'count'];
1500    const writeMethods = ['put', 'add', 'delete', 'clear'];
1501    const cachedMethods = new Map();
1502    function getMethod(target, prop) {
1503        if (!(target instanceof IDBDatabase &&
1504            !(prop in target) &&
1505            typeof prop === 'string')) {
1506            return;
1507        }
1508        if (cachedMethods.get(prop))
1509            return cachedMethods.get(prop);
1510        const targetFuncName = prop.replace(/FromIndex$/, '');
1511        const useIndex = prop !== targetFuncName;
1512        const isWrite = writeMethods.includes(targetFuncName);
1513        if (
1514        // Bail if the target doesn't exist on the target. Eg, getAll isn't in Edge.
1515        !(targetFuncName in (useIndex ? IDBIndex : IDBObjectStore).prototype) ||
1516            !(isWrite || readMethods.includes(targetFuncName))) {
1517            return;
1518        }
1519        const method = async function (storeName, ...args) {
1520            // isWrite ? 'readwrite' : undefined gzipps better, but fails in Edge :(
1521            const tx = this.transaction(storeName, isWrite ? 'readwrite' : 'readonly');
1522            let target = tx.store;
1523            if (useIndex)
1524                target = target.index(args.shift());
1525            // Must reject if op rejects.
1526            // If it's a write operation, must reject if tx.done rejects.
1527            // Must reject with op rejection first.
1528            // Must resolve with op value.
1529            // Must handle both promises (no unhandled rejections)
1530            return (await Promise.all([
1531                target[targetFuncName](...args),
1532                isWrite && tx.done,
1533            ]))[0];
1534        };
1535        cachedMethods.set(prop, method);
1536        return method;
1537    }
1538    replaceTraps((oldTraps) => ({
1539        ...oldTraps,
1540        get: (target, prop, receiver) => getMethod(target, prop) || oldTraps.get(target, prop, receiver),
1541        has: (target, prop) => !!getMethod(target, prop) || oldTraps.has(target, prop),
1542    }));
1543
1544    /**
1545     * @license
1546     * Copyright 2019 Google LLC
1547     *
1548     * Licensed under the Apache License, Version 2.0 (the "License");
1549     * you may not use this file except in compliance with the License.
1550     * You may obtain a copy of the License at
1551     *
1552     *   http://www.apache.org/licenses/LICENSE-2.0
1553     *
1554     * Unless required by applicable law or agreed to in writing, software
1555     * distributed under the License is distributed on an "AS IS" BASIS,
1556     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1557     * See the License for the specific language governing permissions and
1558     * limitations under the License.
1559     */
1560    class PlatformLoggerServiceImpl {
1561        constructor(container) {
1562            this.container = container;
1563        }
1564        // In initial implementation, this will be called by installations on
1565        // auth token refresh, and installations will send this string.
1566        getPlatformInfoString() {
1567            const providers = this.container.getProviders();
1568            // Loop through providers and get library/version pairs from any that are
1569            // version components.
1570            return providers
1571                .map(provider => {
1572                if (isVersionServiceProvider(provider)) {
1573                    const service = provider.getImmediate();
1574                    return `${service.library}/${service.version}`;
1575                }
1576                else {
1577                    return null;
1578                }
1579            })
1580                .filter(logString => logString)
1581                .join(' ');
1582        }
1583    }
1584    /**
1585     *
1586     * @param provider check if this provider provides a VersionService
1587     *
1588     * NOTE: Using Provider<'app-version'> is a hack to indicate that the provider
1589     * provides VersionService. The provider is not necessarily a 'app-version'
1590     * provider.
1591     */
1592    function isVersionServiceProvider(provider) {
1593        const component = provider.getComponent();
1594        return component?.type === "VERSION" /* ComponentType.VERSION */;
1595    }
1596
1597    const name$q = "@firebase/app";
1598    const version$1$1 = "0.14.13";
1599
1600    /**
1601     * @license
1602     * Copyright 2019 Google LLC
1603     *
1604     * Licensed under the Apache License, Version 2.0 (the "License");
1605     * you may not use this file except in compliance with the License.
1606     * You may obtain a copy of the License at
1607     *
1608     *   http://www.apache.org/licenses/LICENSE-2.0
1609     *
1610     * Unless required by applicable law or agreed to in writing, software
1611     * distributed under the License is distributed on an "AS IS" BASIS,
1612     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1613     * See the License for the specific language governing permissions and
1614     * limitations under the License.
1615     */
1616    const logger = new Logger('@firebase/app');
1617
1618    const name$p = "@firebase/app-compat";
1619
1620    const name$o = "@firebase/analytics-compat";
1621
1622    const name$n = "@firebase/analytics";
1623
1624    const name$m = "@firebase/app-check-compat";
1625
1626    const name$l = "@firebase/app-check";
1627
1628    const name$k = "@firebase/auth";
1629
1630    const name$j = "@firebase/auth-compat";
1631
1632    const name$i = "@firebase/database";
1633
1634    const name$h = "@firebase/data-connect";
1635
1636    const name$g = "@firebase/database-compat";
1637
1638    const name$f = "@firebase/functions";
1639
1640    const name$e = "@firebase/functions-compat";
1641
1642    const name$d = "@firebase/installations";
1643
1644    const name$c = "@firebase/installations-compat";
1645
1646    const name$b = "@firebase/messaging";
1647
1648    const name$a = "@firebase/messaging-compat";
1649
1650    const name$9 = "@firebase/performance";
1651
1652    const name$8 = "@firebase/performance-compat";
1653
1654    const name$7 = "@firebase/remote-config";
1655
1656    const name$6 = "@firebase/remote-config-compat";
1657
1658    const name$5 = "@firebase/storage";
1659
1660    const name$4 = "@firebase/storage-compat";
1661
1662    const name$3 = "@firebase/firestore";
1663
1664    const name$2 = "@firebase/ai";
1665
1666    const name$1$1 = "@firebase/firestore-compat";
1667
1668    const name$r = "firebase";
1669
1670    /**
1671     * @license
1672     * Copyright 2019 Google LLC
1673     *
1674     * Licensed under the Apache License, Version 2.0 (the "License");
1675     * you may not use this file except in compliance with the License.
1676     * You may obtain a copy of the License at
1677     *
1678     *   http://www.apache.org/licenses/LICENSE-2.0
1679     *
1680     * Unless required by applicable law or agreed to in writing, softw
1680are
1681     * distributed under the License is distributed on an "AS IS" BASIS,
1682     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1683     * See the License for the specific language governing permissions and
1684     * limitations under the License.
1685     */
1686    /**
1687     * The default app name
1688     *
1689     * @internal
1690     */
1691    const DEFAULT_ENTRY_NAME = '[DEFAULT]';
1692    const PLATFORM_LOG_STRING = {
1693        [name$q]: 'fire-core',
1694        [name$p]: 'fire-core-compat',
1695        [name$n]: 'fire-analytics',
1696        [name$o]: 'fire-analytics-compat',
1697        [name$l]: 'fire-app-check',
1698        [name$m]: 'fire-app-check-compat',
1699        [name$k]: 'fire-auth',
1700        [name$j]: 'fire-auth-compat',
1701        [name$i]: 'fire-rtdb',
1702        [name$h]: 'fire-data-connect',
1703        [name$g]: 'fire-rtdb-compat',
1704        [name$f]: 'fire-fn',
1705        [name$e]: 'fire-fn-compat',
1706        [name$d]: 'fire-iid',
1707        [name$c]: 'fire-iid-compat',
1708        [name$b]: 'fire-fcm',
1709        [name$a]: 'fire-fcm-compat',
1710        [name$9]: 'fire-perf',
1711        [name$8]: 'fire-perf-compat',
1712        [name$7]: 'fire-rc',
1713        [name$6]: 'fire-rc-compat',
1714        [name$5]: 'fire-gcs',
1715        [name$4]: 'fire-gcs-compat',
1716        [name$3]: 'fire-fst',
1717        [name$1$1]: 'fire-fst-compat',
1718        [name$2]: 'fire-vertex',
1719        'fire-js': 'fire-js', // Platform identifier for JS SDK.
1720        [name$r]: 'fire-js-all'
1721    };
1722
1723    /**
1724     * @license
1725     * Copyright 2019 Google LLC
1726     *
1727     * Licensed under the Apache License, Version 2.0 (the "License");
1728     * you may not use this file except in compliance with the License.
1729     * You may obtain a copy of the License at
1730     *
1731     *   http://www.apache.org/licenses/LICENSE-2.0
1732     *
1733     * Unless required by applicable law or agreed to in writing, software
1734     * distributed under the License is distributed on an "AS IS" BASIS,
1735     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1736     * See the License for the specific language governing permissions and
1737     * limitations under the License.
1738     */
1739    /**
1740     * @internal
1741     */
1742    const _apps = new Map();
1743    /**
1744     * @internal
1745     */
1746    const _serverApps = new Map();
1747    /**
1748     * Registered components.
1749     *
1750     * @internal
1751     */
1752    // eslint-disable-next-line @typescript-eslint/no-explicit-any
1753    const _components = new Map();
1754    /**
1755     * @param component - the component being added to this app's container
1756     *
1757     * @internal
1758     */
1759    function _addComponent(app, component) {
1760        try {
1761            app.container.addComponent(component);
1762        }
1763        catch (e) {
1764            logger.debug(`Component ${component.name} failed to register with FirebaseApp ${app.name}`, e);
1765        }
1766    }
1767    /**
1768     *
1769     * @param component - the component to register
1770     * @returns whether or not the component is registered successfully
1771     *
1772     * @internal
1773     */
1774    function _registerComponent(component) {
1775        const componentName = component.name;
1776        if (_components.has(componentName)) {
1777            logger.debug(`There were multiple attempts to register component ${componentName}.`);
1778            return false;
1779        }
1780        _components.set(componentName, component);
1781        // add the component to existing app instances
1782        for (const app of _apps.values()) {
1783            _addComponent(app, component);
1784        }
1785        for (const serverApp of _serverApps.values()) {
1786            _addComponent(serverApp, component);
1787        }
1788        return true;
1789    }
1790    /**
1791     *
1792     * @param app - FirebaseApp instance
1793     * @param name - service name
1794     *
1795     * @returns the provider for the service with the matching name
1796     *
1797     * @internal
1798     */
1799    function _getProvider(app, name) {
1800        const heartbeatController = app.container
1801            .getProvider('heartbeat')
1802            .getImmediate({ optional: true });
1803        if (heartbeatController) {
1804            void heartbeatController.triggerHeartbeat();
1805        }
1806        return app.container.getProvider(name);
1807    }
1808
1809    /**
1810     * @license
1811     * Copyright 2019 Google LLC
1812     *
1813     * Licensed under the Apache License, Version 2.0 (the "License");
1814     * you may not use this file except in compliance with the License.
1815     * You may obtain a copy of the License at
1816     *
1817     *   http://www.apache.org/licenses/LICENSE-2.0
1818     *
1819     * Unless required by applicable law or agreed to in writing, software
1820     * distributed under the License is distributed on an "AS IS" BASIS,
1821     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1822     * See the License for the specific language governing permissions and
1823     * limitations under the License.
1824     */
1825    const ERRORS = {
1826        ["no-app" /* AppError.NO_APP */]: "No Firebase App '{$appName}' has been created - " +
1827            'call initializeApp() first',
1828        ["bad-app-name" /* AppError.BAD_APP_NAME */]: "Illegal App name: '{$appName}'",
1829        ["duplicate-app" /* AppError.DUPLICATE_APP */]: "Firebase App named '{$appName}' already exists with different options or config",
1830        ["app-deleted" /* AppError.APP_DELETED */]: "Firebase App named '{$appName}' already deleted",
1831        ["server-app-deleted" /* AppError.SERVER_APP_DELETED */]: 'Firebase Server App has been deleted',
1832        ["no-options" /* AppError.NO_OPTIONS */]: 'Need to provide options, when not being deployed to hosting via source.',
1833        ["invalid-app-argument" /* AppError.INVALID_APP_ARGUMENT */]: 'firebase.{$appName}() takes either no argument or a ' +
1834            'Firebase App instance.',
1835        ["invalid-log-argument" /* AppError.INVALID_LOG_ARGUMENT */]: 'First argument to `onLog` must be null or a function.',
1836        ["idb-open" /* AppError.IDB_OPEN */]: 'Error thrown when opening IndexedDB. Original error: {$originalErrorMessage}.',
1837        ["idb-get" /* AppError.IDB_GET */]: 'Error thrown when reading from IndexedDB. Original error: {$originalErrorMessage}.',
1838        ["idb-set" /* AppError.IDB_WRITE */]: 'Error thrown when writing to IndexedDB. Original error: {$originalErrorMessage}.',
1839        ["idb-delete" /* AppError.IDB_DELETE */]: 'Error thrown when deleting from IndexedDB. Original error: {$originalErrorMessage}.',
1840        ["finalization-registry-not-supported" /* AppError.FINALIZATION_REGISTRY_NOT_SUPPORTED */]: 'FirebaseServerApp deleteOnDeref field defined but the JS runtime does not support FinalizationRegistry.',
1841        ["invalid-server-app-environment" /* AppError.INVALID_SERVER_APP_ENVIRONMENT */]: 'FirebaseServerApp is not for use in browser environments.'
1842    };
1843    const ERROR_FACTORY$2 = new ErrorFactory('app', 'Firebase', ERRORS);
1844
1845    /**
1846     * @license
1847     * Copyright 2019 Google LLC
1848     *
1849     * Licensed under the Apache License, Version 2.0 (the "License");
1850     * you may not use this file except in compliance with the License.
1851     * You may obtain a copy of the License at
1852     *
1853     *   http://www.apache.org/licenses/LICENSE-2.0
1854     *
1855     * Unless required by applicable law or agreed to in writing, software
1856     * distributed under the License is distributed on an "AS IS" BASIS,
1857     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1858     * See the License for the specific language governing permissions and
1859     * limitations under the License.
1860     */
1861    class FirebaseAppImpl {
1862        constructor(options, config, container) {
1863            this._isDeleted = false;
1864            this._options = { ...options };
1865            this._config = { ...config };
1866            this._name = config.name;
1867            this._automaticDataCollectionEnabled =
1868                config.automaticDataCollectionEnabled;
1869            this._container = container;
1870            this.container.addComponent(new Component('app', () => this, "PUBLIC" /* ComponentType.PUBLIC */));
1871        }
1872        get automaticDataCollectionEnabled() {
1873            this.checkDestroyed();
1874            return this._automaticDataCollectionEnabled;
1875        }
1876        set automaticDataCollectionEnabled(val) {
1877            this.checkDestroyed();
1878            this._automaticDataCollectionEnabled = val;
1879        }
1880        get name() {
1881            this.checkDestroyed();
1882            return this._name;
1883        }
1884        get options() {
1885            this.checkDestroyed();
1886            return this._options;
1887        }
1888        get config() {
1889            this.checkDestroyed();
1890            return this._config;
1891        }
1892        get container() {
1893            return this._container;
1894        }
1895        get isDeleted() {
1896            return this._isDeleted;
1897        }
1898        set isDeleted(val) {
1899            this._isDeleted = val;
1900        }
1901        /**
1902         * This function will throw an Error if the App has already been deleted -
1903         * use before performing API actions on the App.
1904         */
1905        checkDestroyed() {
1906            if (this.isDeleted) {
1907                throw ERROR_FACTORY$2.create("app-deleted" /* AppError.APP_DELETED */, { appName: this._name });
1908            }
1909        }
1910    }
1911    function initializeApp(_options, rawConfig = {}) {
1912        let options = _options;
1913        if (typeof rawConfig !== 'object') {
1914            const name = rawConfig;
1915            rawConfig = { name };
1916        }
1917        const config = {
1918            name: DEFAULT_ENTRY_NAME,
1919            automaticDataCollectionEnabled: true,
1920            ...rawConfig
1921        };
1922        const name = config.name;
1923        if (typeof name !== 'string' || !name) {
1924            throw ERROR_FACTORY$2.create("bad-app-name" /* AppError.BAD_APP_NAME */, {
1925                appName: String(name)
1926            });
1927        }
1928        options || (options = getDefaultAppConfig());
1929        if (!options) {
1930            throw ERROR_FACTORY$2.create("no-options" /* AppError.NO_OPTIONS */);
1931        }
1932        const existingApp = _apps.get(name);
1933        if (existingApp) {
1934            // return the existing app if options and config deep equal the ones in the existing app.
1935            if (deepEqual(options, existingApp.options) &&
1936                deepEqual(config, existingApp.config)) {
1937                return existingApp;
1938            }
1939            else {
1940                throw ERROR_FACTORY$2.create("duplicate-app" /* AppError.DUPLICATE_APP */, { appName: name });
1941            }
1942        }
1943        const container = new ComponentContainer(name);
1944        for (const component of _components.values()) {
1945            container.addComponent(component);
1946        }
1947        const newApp = new FirebaseAppImpl(options, config, container);
1948        _apps.set(name, newApp);
1949        return newApp;
1950    }
1951    /**
1952     * Retrieves a {@link @firebase/app#FirebaseApp} instance.
1953     *
1954     * When called with no arguments, the default app is returned. When an app name
1955     * is provided, the app corresponding to that name is returned.
1956     *
1957     * An exception is thrown if the app being retrieved has not yet been
1958     * initialized.
1959     *
1960     * @example
1961     * ```javascript
1962     * // Return the default app
1963     * const app = getApp();
1964     * ```
1965     *
1966     * @example
1967     * ```javascript
1968     * // Return a named app
1969     * const otherApp = getApp("otherApp");
1970     * ```
1971     *
1972     * @param name - Optional name of the app to return. If no name is
1973     *   provided, the default is `"[DEFAULT]"`.
1974     *
1975     * @returns The app corresponding to the provided app name.
1976     *   If no app name is provided, the default app is returned.
1977     *
1978     * @public
1979     */
1980    function getApp(name = DEFAULT_ENTRY_NAME) {
1981        const app = _apps.get(name);
1982        if (!app && name === DEFAULT_ENTRY_NAME && getDefaultAppConfig()) {
1983            return initializeApp();
1984        }
1985        if (!app) {
1986            throw ERROR_FACTORY$2.create("no-app" /* AppError.NO_APP */, { appName: name });
1987        }
1988        return app;
1989    }
1990    /**
1991     * Registers a library's name and version for platform logging purposes.
1992     * @param library - Name of 1p or 3p library (e.g. firestore, angularfire)
1993     * @param version - Current version of that library.
1994     * @param variant - Bundle variant, e.g., node, rn, etc.
1995     *
1996     * @public
1997     */
1998    function registerVersion(libraryKeyOrName, version, variant) {
1999        // TODO: We can use this check to whitelist strings when/if we set up
2000        // a good whitelist system.
2001        let library = PLATFORM_LOG_STRING[libraryKeyOrName] ?? libraryKeyOrName;
2002        if (variant) {
2003            library += `-${variant}`;
2004        }
2005        const libraryMismatch = library.match(/\s|\//);
2006        const versionMismatch = version.match(/\s|\//);
2007        if (libraryMismatch || versionMismatch) {
2008            const warning = [
2009                `Unable to register library "${library}" with version "${version}":`
2010            ];
2011            if (libraryMismatch) {
2012                warning.push(`library name "${library}" contains illegal characters (whitespace or "/")`);
2013            }
2014            if (libraryMismatch && versionMismatch) {
2015                warning.push('and');
2016            }
2017            if (versionMismatch) {
2018                warning.push(`version name "${version}" contains illegal characters (whitespace or "/")`);
2019            }
2020            logger.warn(warning.join(' '));
2021            return;
2022        }
2023        _registerComponent(new Component(`${library}-version`, () => ({ library, version }), "VERSION" /* ComponentType.VERSION */));
2024    }
2025
2026    /**
2027     * @license
2028     * Copyright 2021 Google LLC
2029     *
2030     * Licensed under the Apache License, Version 2.0 (the "License");
2031     * you may not use this file except in compliance with the License.
2032     * You may obtain a copy of the License at
2033     *
2034     *   http://www.apache.org/licenses/LICENSE-2.0
2035     *
2036     * Unless required by applicable law or agreed to in writing, softw
vendor: 15,867 bytes, lines 2036-2395
2036are
2037     * distributed under the License is distributed on an "AS IS" BASIS,
2038     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2039     * See the License for the specific language governing permissions and
2040     * limitations under the License.
2041     */
2042    const DB_NAME = 'firebase-heartbeat-database';
2043    const DB_VERSION = 1;
2044    const STORE_NAME = 'firebase-heartbeat-store';
2045    let dbPromise$2 = null;
2046    function getDbPromise$2() {
2047        if (!dbPromise$2) {
2048            dbPromise$2 = openDB(DB_NAME, DB_VERSION, {
2049                upgrade: (db, oldVersion) => {
2050                    // We don't use 'break' in this switch statement, the fall-through
2051                    // behavior is what we want, because if there are multiple versions between
2052                    // the old version and the current version, we want ALL the migrations
2053                    // that correspond to those versions to run, not only the last one.
2054                    // eslint-disable-next-line default-case
2055                    switch (oldVersion) {
2056                        case 0:
2057                            try {
2058                                db.createObjectStore(STORE_NAME);
2059                            }
2060                            catch (e) {
2061                                // Safari/iOS browsers throw occasional exceptions on
2062                                // db.createObjectStore() that may be a bug. Avoid blocking
2063                                // the rest of the app functionality.
2064                                console.warn(e);
2065                            }
2066                    }
2067                }
2068            }).catch(e => {
2069                throw ERROR_FACTORY$2.create("idb-open" /* AppError.IDB_OPEN */, {
2070                    originalErrorMessage: e.message
2071                });
2072            });
2073        }
2074        return dbPromise$2;
2075    }
2076    async function readHeartbeatsFromIndexedDB(app) {
2077        try {
2078            const db = await getDbPromise$2();
2079            const tx = db.transaction(STORE_NAME);
2080            const result = await tx.objectStore(STORE_NAME).get(computeKey(app));
2081            // We already have the value but tx.done can throw,
2082            // so we need to await it here to catch errors
2083            await tx.done;
2084            return result;
2085        }
2086        catch (e) {
2087            if (e instanceof FirebaseError) {
2088                logger.warn(e.message);
2089            }
2090            else {
2091                const idbGetError = ERROR_FACTORY$2.create("idb-get" /* AppError.IDB_GET */, {
2092                    originalErrorMessage: e?.message
2093                });
2094                logger.warn(idbGetError.message);
2095            }
2096        }
2097    }
2098    async function writeHeartbeatsToIndexedDB(app, heartbeatObject) {
2099        try {
2100            const db = await getDbPromise$2();
2101            const tx = db.transaction(STORE_NAME, 'readwrite');
2102            const objectStore = tx.objectStore(STORE_NAME);
2103            await objectStore.put(heartbeatObject, computeKey(app));
2104            await tx.done;
2105        }
2106        catch (e) {
2107            if (e instanceof FirebaseError) {
2108                logger.warn(e.message);
2109            }
2110            else {
2111                const idbGetError = ERROR_FACTORY$2.create("idb-set" /* AppError.IDB_WRITE */, {
2112                    originalErrorMessage: e?.message
2113                });
2114                logger.warn(idbGetError.message);
2115            }
2116        }
2117    }
2118    function computeKey(app) {
2119        return `${app.name}!${app.options.appId}`;
2120    }
2121
2122    /**
2123     * @license
2124     * Copyright 2021 Google LLC
2125     *
2126     * Licensed under the Apache License, Version 2.0 (the "License");
2127     * you may not use this file except in compliance with the License.
2128     * You may obtain a copy of the License at
2129     *
2130     *   http://www.apache.org/licenses/LICENSE-2.0
2131     *
2132     * Unless required by applicable law or agreed to in writing, software
2133     * distributed under the License is distributed on an "AS IS" BASIS,
2134     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2135     * See the License for the specific language governing permissions and
2136     * limitations under the License.
2137     */
2138    const MAX_HEADER_BYTES = 1024;
2139    const MAX_NUM_STORED_HEARTBEATS = 30;
2140    class HeartbeatServiceImpl {
2141        constructor(container) {
2142            this.container = container;
2143            /**
2144             * In-memory cache for heartbeats, used by getHeartbeatsHeader() to generate
2145             * the header string.
2146             * Stores one record per date. This will be consolidated into the standard
2147             * format of one record per user agent string before being sent as a header.
2148             * Populated from indexedDB when the controller is instantiated and should
2149             * be kept in sync with indexedDB.
2150             * Leave public for easier testing.
2151             */
2152            this._heartbeatsCache = null;
2153            const app = this.container.getProvider('app').getImmediate();
2154            this._storage = new HeartbeatStorageImpl(app);
2155            this._heartbeatsCachePromise = this._storage.read().then(result => {
2156                this._heartbeatsCache = result;
2157                return result;
2158            });
2159        }
2160        /**
2161         * Called to report a heartbeat. The function will generate
2162         * a HeartbeatsByUserAgent object, update heartbeatsCache, and persist it
2163         * to IndexedDB.
2164         * Note that we only store one heartbeat per day. So if a heartbeat for today is
2165         * already logged, subsequent calls to this function in the same day will be ignored.
2166         */
2167        async triggerHeartbeat() {
2168            try {
2169                const platformLogger = this.container
2170                    .getProvider('platform-logger')
2171                    .getImmediate();
2172                // This is the "Firebase user agent" string from the platform logger
2173                // service, not the browser user agent.
2174                const agent = platformLogger.getPlatformInfoString();
2175                const date = getUTCDateString();
2176                if (this._heartbeatsCache?.heartbeats == null) {
2177                    this._heartbeatsCache = await this._heartbeatsCachePromise;
2178                    // If we failed to construct a heartbeats cache, then return immediately.
2179                    if (this._heartbeatsCache?.heartbeats == null) {
2180                        return;
2181                    }
2182                }
2183                // Do not store a heartbeat if one is already stored for this day
2184                // or if a header has already been sent today.
2185                if (this._heartbeatsCache.lastSentHeartbeatDate === date ||
2186                    this._heartbeatsCache.heartbeats.some(singleDateHeartbeat => singleDateHeartbeat.date === date)) {
2187                    return;
2188                }
2189                else {
2190                    // There is no entry for this date. Create one.
2191                    this._heartbeatsCache.heartbeats.push({ date, agent });
2192                    // If the number of stored heartbeats exceeds the maximum number of stored heartbeats, remove the heartbeat with the earliest date.
2193                    // 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.
2194                    if (this._heartbeatsCache.heartbeats.length > MAX_NUM_STORED_HEARTBEATS) {
2195                        const earliestHeartbeatIdx = getEarliestHeartbeatIdx(this._heartbeatsCache.heartbeats);
2196                        this._heartbeatsCache.heartbeats.splice(earliestHeartbeatIdx, 1);
2197                    }
2198                }
2199                return this._storage.overwrite(this._heartbeatsCache);
2200            }
2201            catch (e) {
2202                logger.warn(e);
2203            }
2204        }
2205        /**
2206         * Returns a base64 encoded string which can be attached to the heartbeat-specific header directly.
2207         * It also clears all heartbeats from memory as well as in IndexedDB.
2208         *
2209         * NOTE: Consuming product SDKs should not send the header if this method
2210         * returns an empty string.
2211         */
2212        async getHeartbeatsHeader() {
2213            try {
2214                if (this._heartbeatsCache === null) {
2215                    await this._heartbeatsCachePromise;
2216                }
2217                // If it's still null or the array is empty, there is no data to send.
2218                if (this._heartbeatsCache?.heartbeats == null ||
2219                    this._heartbeatsCache.heartbeats.length === 0) {
2220                    return '';
2221                }
2222                const date = getUTCDateString();
2223                // Extract as many heartbeats from the cache as will fit under the size limit.
2224                const { heartbeatsToSend, unsentEntries } = extractHeartbeatsForHeader(this._heartbeatsCache.heartbeats);
2225                const headerString = base64urlEncodeWithoutPadding(JSON.stringify({ version: 2, heartbeats: heartbeatsToSend }));
2226                // Store last sent date to prevent another being logged/sent for the same day.
2227                this._heartbeatsCache.lastSentHeartbeatDate = date;
2228                if (unsentEntries.length > 0) {
2229                    // Store any unsent entries if they exist.
2230                    this._heartbeatsCache.heartbeats = unsentEntries;
2231                    // This seems more likely than emptying the array (below) to lead to some odd state
2232                    // since the cache isn't empty and this will be called again on the next request,
2233                    // and is probably safest if we await it.
2234                    await this._storage.overwrite(this._heartbeatsCache);
2235                }
2236                else {
2237                    this._heartbeatsCache.heartbeats = [];
2238                    // Do not wait for this, to reduce latency.
2239                    void this._storage.overwrite(this._heartbeatsCache);
2240                }
2241                return headerString;
2242            }
2243            catch (e) {
2244                logger.warn(e);
2245                return '';
2246            }
2247        }
2248    }
2249    function getUTCDateString() {
2250        const today = new Date();
2251        // Returns date format 'YYYY-MM-DD'
2252        return today.toISOString().substring(0, 10);
2253    }
2254    function extractHeartbeatsForHeader(heartbeatsCache, maxSize = MAX_HEADER_BYTES) {
2255        // Heartbeats grouped by user agent in the standard format to be sent in
2256        // the header.
2257        const heartbeatsToSend = [];
2258        // Single date format heartbeats that are not sent.
2259        let unsentEntries = heartbeatsCache.slice();
2260        for (const singleDateHeartbeat of heartbeatsCache) {
2261            // Look for an existing entry with the same user agent.
2262            const heartbeatEntry = heartbeatsToSend.find(hb => hb.agent === singleDateHeartbeat.agent);
2263            if (!heartbeatEntry) {
2264                // If no entry for this user agent exists, create one.
2265                heartbeatsToSend.push({
2266                    agent: singleDateHeartbeat.agent,
2267                    dates: [singleDateHeartbeat.date]
2268                });
2269                if (countBytes(heartbeatsToSend) > maxSize) {
2270                    // If the header would exceed max size, remove the added heartbeat
2271                    // entry and stop adding to the header.
2272                    heartbeatsToSend.pop();
2273                    break;
2274                }
2275            }
2276            else {
2277                heartbeatEntry.dates.push(singleDateHeartbeat.date);
2278                // If the header would exceed max size, remove the added date
2279                // and stop adding to the header.
2280                if (countBytes(heartbeatsToSend) > maxSize) {
2281                    heartbeatEntry.dates.pop();
2282                    break;
2283                }
2284            }
2285            // Pop unsent entry from queue. (Skipped if adding the entry exceeded
2286            // quota and the loop breaks early.)
2287            unsentEntries = unsentEntries.slice(1);
2288        }
2289        return {
2290            heartbeatsToSend,
2291            unsentEntries
2292        };
2293    }
2294    class HeartbeatStorageImpl {
2295        constructor(app) {
2296            this.app = app;
2297            this._canUseIndexedDBPromise = this.runIndexedDBEnvironmentCheck();
2298        }
2299        async runIndexedDBEnvironmentCheck() {
2300            if (!isIndexedDBAvailable()) {
2301                return false;
2302            }
2303            else {
2304                return validateIndexedDBOpenable()
2305                    .then(() => true)
2306                    .catch(() => false);
2307            }
2308        }
2309        /**
2310         * Read all heartbeats.
2311         */
2312        async read() {
2313            const canUseIndexedDB = await this._canUseIndexedDBPromise;
2314            if (!canUseIndexedDB) {
2315                return { heartbeats: [] };
2316            }
2317            else {
2318                const idbHeartbeatObject = await readHeartbeatsFromIndexedDB(this.app);
2319                if (idbHeartbeatObject?.heartbeats) {
2320                    return idbHeartbeatObject;
2321                }
2322                else {
2323                    return { heartbeats: [] };
2324                }
2325            }
2326        }
2327        // overwrite the storage with the provided heartbeats
2328        async overwrite(heartbeatsObject) {
2329            const canUseIndexedDB = await this._canUseIndexedDBPromise;
2330            if (!canUseIndexedDB) {
2331                return;
2332            }
2333            else {
2334                const existingHeartbeatsObject = await this.read();
2335                return writeHeartbeatsToIndexedDB(this.app, {
2336                    lastSentHeartbeatDate: heartbeatsObject.lastSentHeartbeatDate ??
2337                        existingHeartbeatsObject.lastSentHeartbeatDate,
2338                    heartbeats: heartbeatsObject.heartbeats
2339                });
2340            }
2341        }
2342        // add heartbeats
2343        async add(heartbeatsObject) {
2344            const canUseIndexedDB = await this._canUseIndexedDBPromise;
2345            if (!canUseIndexedDB) {
2346                return;
2347            }
2348            else {
2349                const existingHeartbeatsObject = await this.read();
2350                return writeHeartbeatsToIndexedDB(this.app, {
2351                    lastSentHeartbeatDate: heartbeatsObject.lastSentHeartbeatDate ??
2352                        existingHeartbeatsObject.lastSentHeartbeatDate,
2353                    heartbeats: [
2354                        ...existingHeartbeatsObject.heartbeats,
2355                        ...heartbeatsObject.heartbeats
2356                    ]
2357                });
2358            }
2359        }
2360    }
2361    /**
2362     * Calculate bytes of a HeartbeatsByUserAgent array after being wrapped
2363     * in a platform logging header JSON object, stringified, and converted
2364     * to base 64.
2365     */
2366    function countBytes(heartbeatsCache) {
2367        // base64 has a restricted set of characters, all of which should be 1 byte.
2368        return base64urlEncodeWithoutPadding(
2369        // heartbeatsCache wrapper properties
2370        JSON.stringify({ version: 2, heartbeats: heartbeatsCache })).length;
2371    }
2372    /**
2373     * Returns the index of the heartbeat with the earliest date.
2374     * If the heartbeats array is empty, -1 is returned.
2375     */
2376    function getEarliestHeartbeatIdx(heartbeats) {
2377        if (heartbeats.length === 0) {
2378            return -1;
2379        }
2380        let earliestHeartbeatIdx = 0;
2381        let earliestHeartbeatDate = heartbeats[0].date;
2382        for (let i = 1; i < heartbeats.length; i++) {
2383            if (heartbeats[i].date < earliestHeartbeatDate) {
2384                earliestHeartbeatDate = heartbeats[i].date;
2385                earliestHeartbeatIdx = i;
2386            }
2387        }
2388        return earliestHeartbeatIdx;
2389    }
2390
2391    /**
2392     * @license
2393     * Copyright 2019 Google LLC
2394     *
2395     * Licensed under the Apache License, Version 2.0 (the "License");
2396     * you may not use this file except in compliance with the License.
2397     * You may obtain a copy of the License at
2398     *
2399     *   http://www.apache.org/licenses/LICENSE-2.0
2400     *
2401     * Unless required by applicable law or agreed to in writing, software
2402     * distributed under the License is distributed on an "AS IS" BASIS,
2403     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2404     * See the License for the specific language governing permissions and
2405     * limitations under the License.
2406     */
2407    function registerCoreComponents(variant) {
2408        _registerComponent(new Component('platform-logger', container => new PlatformLoggerServiceImpl(container), "PRIVATE" /* ComponentType.PRIVATE */));
2409        _registerComponent(new Component('heartbeat', container => new HeartbeatServiceImpl(container), "PRIVATE" /* ComponentType.PRIVATE */));
2410        // Register `app` package.
2411        registerVersion(name$q, version$1$1, variant);
2412        // BUILD_TARGET will be replaced by values like esm, cjs, etc during the compilation
2413        registerVersion(name$q, version$1$1, 'esm2020');
2414        // Register platform SDK identifier (no version).
2415        registerVersion('fire-js', '');
2416    }
2417
2418    /**
2419     * Firebase App
2420     *
2421     * @remarks This package coordinates the communication between the different Firebase components
2422     * @packageDocumentation
2423     */
2424    registerCoreComponents('');
2425
2426    var name$1 = "firebase";
2427    var version$2 = "12.14.0";
2428
2429    /**
2430     * @license
2431     * Copyright 2020 Google LLC
2432     *
2433     * Licensed under the Apache License, Version 2.0 (the "License");
2434     * you may not use this file except in compliance with the License.
2435     * You may obtain a copy of the License at
2436     *
2437     *   http://www.apache.org/licenses/LICENSE-2.0
2438     *
2439     * Unless required by applicable law or agreed to in writing, software
2440     * distributed under the License is distributed on an "AS IS" BASIS,
2441     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2442     * See the License for the specific language governing permissions and
2443     * limitations under the License.
2444     */
2445    registerVersion(name$1, version$2, 'app');
2446
2447    const name = "@firebase/installations";
2448    const version$1 = "0.6.22";
2449
2450    /**
2451     * @license
2452     * Copyright 2019 Google LLC
2453     *
2454     * Licensed under the Apache License, Version 2.0 (the "License");
2455     * you may not use this file except in compliance with the License.
2456     * You may obtain a copy of the License at
2457     *
2458     *   http://www.apache.org/licenses/LICENSE-2.0
2459     *
2460     * Unless required by applicable law or agreed to in writing, software
2461     * distributed under the License is distributed on an "AS IS" BASIS,
2462     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2463     * See the License for the specific language governing permissions and
2464     * limitations under the License.
2465     */
2466    const PENDING_TIMEOUT_MS = 10000;
2467    const PACKAGE_VERSION = `w:${version$1}`;
2468    const INTERNAL_AUTH_VERSION = 'FIS_v2';
2469    const INSTALLATIONS_API_URL = 'https://firebaseinstallations.googleapis.com/v1';
2470    const TOKEN_EXPIRATION_BUFFER = 60 * 60 * 1000; // One hour
2471    const SERVICE = 'installations';
2472    const SERVICE_NAME = 'Installations';
2473
2474    /**
2475     * @license
2476     * Copyright 2019 Google LLC
2477     *
2478     * Licensed under the Apache License, Version 2.0 (the "License");
2479     * you may not use this file except in compliance with the License.
2480     * You may obtain a copy of the License at
2481     *
2482     *   http://www.apache.org/licenses/LICENSE-2.0
2483     *
2484     * Unless required by applicable law or agreed to in writing, software
2485     * distributed under the License is distributed on an "AS IS" BASIS,
2486     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2487     * See the License for the specific language governing permissions and
2488     * limitations under the License.
2489     */
2490    const ERROR_DESCRIPTION_MAP = {
2491        ["missing-app-config-values" /* ErrorCode.MISSING_APP_CONFIG_VALUES */]: 'Missing App configuration value: "{$valueName}"',
2492        ["not-registered" /* ErrorCode.NOT_REGISTERED */]: 'Firebase Installation is not registered.',
2493        ["installation-not-found" /* ErrorCode.INSTALLATION_NOT_FOUND */]: 'Firebase Installation not found.',
2494        ["request-failed" /* ErrorCode.REQUEST_FAILED */]: '{$requestName} request failed with error "{$serverCode} {$serverStatus}: {$serverMessage}"',
2495        ["app-offline" /* ErrorCode.APP_OFFLINE */]: 'Could not process request. Application offline.',
2496        ["delete-pending-registration" /* ErrorCode.DELETE_PENDING_REGISTRATION */]: "Can't delete installation while there is a pending registration request."
2497    };
2498    const ERROR_FACTORY$1 = new ErrorFactory(SERVICE, SERVICE_NAME, ERROR_DESCRIPTION_MAP);
2499    /** Returns true if error is a FirebaseError that is based on an error from the server. */
2500    function isServerError(error) {
2501        return (error instanceof FirebaseError &&
2502            error.code.includes("request-failed" /* ErrorCode.REQUEST_FAILED */)
vendor: 8,898 bytes, lines 2502-2726
2502);
2503    }
2504
2505    /**
2506     * @license
2507     * Copyright 2019 Google LLC
2508     *
2509     * Licensed under the Apache License, Version 2.0 (the "License");
2510     * you may not use this file except in compliance with the License.
2511     * You may obtain a copy of the License at
2512     *
2513     *   http://www.apache.org/licenses/LICENSE-2.0
2514     *
2515     * Unless required by applicable law or agreed to in writing, software
2516     * distributed under the License is distributed on an "AS IS" BASIS,
2517     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2518     * See the License for the specific language governing permissions and
2519     * limitations under the License.
2520     */
2521    function getInstallationsEndpoint({ projectId }) {
2522        return `${INSTALLATIONS_API_URL}/projects/${projectId}/installations`;
2523    }
2524    function extractAuthTokenInfoFromResponse(response) {
2525        return {
2526            token: response.token,
2527            requestStatus: 2 /* RequestStatus.COMPLETED */,
2528            expiresIn: getExpiresInFromResponseExpiresIn(response.expiresIn),
2529            creationTime: Date.now()
2530        };
2531    }
2532    async function getErrorFromResponse(requestName, response) {
2533        const responseJson = await response.json();
2534        const errorData = responseJson.error;
2535        return ERROR_FACTORY$1.create("request-failed" /* ErrorCode.REQUEST_FAILED */, {
2536            requestName,
2537            serverCode: errorData.code,
2538            serverMessage: errorData.message,
2539            serverStatus: errorData.status
2540        });
2541    }
2542    function getHeaders$1({ apiKey }) {
2543        return new Headers({
2544            'Content-Type': 'application/json',
2545            Accept: 'application/json',
2546            'x-goog-api-key': apiKey
2547        });
2548    }
2549    function getHeadersWithAuth(appConfig, { refreshToken }) {
2550        const headers = getHeaders$1(appConfig);
2551        headers.append('Authorization', getAuthorizationHeader(refreshToken));
2552        return headers;
2553    }
2554    /**
2555     * Calls the passed in fetch wrapper and returns the response.
2556     * If the returned response has a status of 5xx, re-runs the function once and
2557     * returns the response.
2558     */
2559    async function retryIfServerError(fn) {
2560        const result = await fn();
2561        if (result.status >= 500 && result.status < 600) {
2562            // Internal Server Error. Retry request.
2563            return fn();
2564        }
2565        return result;
2566    }
2567    function getExpiresInFromResponseExpiresIn(responseExpiresIn) {
2568        // This works because the server will never respond with fractions of a second.
2569        return Number(responseExpiresIn.replace('s', '000'));
2570    }
2571    function getAuthorizationHeader(refreshToken) {
2572        return `${INTERNAL_AUTH_VERSION} ${refreshToken}`;
2573    }
2574
2575    /**
2576     * @license
2577     * Copyright 2019 Google LLC
2578     *
2579     * Licensed under the Apache License, Version 2.0 (the "License");
2580     * you may not use this file except in compliance with the License.
2581     * You may obtain a copy of the License at
2582     *
2583     *   http://www.apache.org/licenses/LICENSE-2.0
2584     *
2585     * Unless required by applicable law or agreed to in writing, software
2586     * distributed under the License is distributed on an "AS IS" BASIS,
2587     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2588     * See the License for the specific language governing permissions and
2589     * limitations under the License.
2590     */
2591    async function createInstallationRequest({ appConfig, heartbeatServiceProvider }, { fid }) {
2592        const endpoint = getInstallationsEndpoint(appConfig);
2593        const headers = getHeaders$1(appConfig);
2594        // If heartbeat service exists, add the heartbeat string to the header.
2595        const heartbeatService = heartbeatServiceProvider.getImmediate({
2596            optional: true
2597        });
2598        if (heartbeatService) {
2599            const heartbeatsHeader = await heartbeatService.getHeartbeatsHeader();
2600            if (heartbeatsHeader) {
2601                headers.append('x-firebase-client', heartbeatsHeader);
2602            }
2603        }
2604        const body = {
2605            fid,
2606            authVersion: INTERNAL_AUTH_VERSION,
2607            appId: appConfig.appId,
2608            sdkVersion: PACKAGE_VERSION
2609        };
2610        const request = {
2611            method: 'POST',
2612            headers,
2613            body: JSON.stringify(body)
2614        };
2615        const response = await retryIfServerError(() => fetch(endpoint, request));
2616        if (response.ok) {
2617            const responseValue = await response.json();
2618            const registeredInstallationEntry = {
2619                fid: responseValue.fid || fid,
2620                registrationStatus: 2 /* RequestStatus.COMPLETED */,
2621                refreshToken: responseValue.refreshToken,
2622                authToken: extractAuthTokenInfoFromResponse(responseValue.authToken)
2623            };
2624            return registeredInstallationEntry;
2625        }
2626        else {
2627            throw await getErrorFromResponse('Create Installation', response);
2628        }
2629    }
2630
2631    /**
2632     * @license
2633     * Copyright 2019 Google LLC
2634     *
2635     * Licensed under the Apache License, Version 2.0 (the "License");
2636     * you may not use this file except in compliance with the License.
2637     * You may obtain a copy of the License at
2638     *
2639     *   http://www.apache.org/licenses/LICENSE-2.0
2640     *
2641     * Unless required by applicable law or agreed to in writing, software
2642     * distributed under the License is distributed on an "AS IS" BASIS,
2643     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2644     * See the License for the specific language governing permissions and
2645     * limitations under the License.
2646     */
2647    /** Returns a promise that resolves after given time passes. */
2648    function sleep$1(ms) {
2649        return new Promise(resolve => {
2650            setTimeout(resolve, ms);
2651        });
2652    }
2653
2654    /**
2655     * @license
2656     * Copyright 2019 Google LLC
2657     *
2658     * Licensed under the Apache License, Version 2.0 (the "License");
2659     * you may not use this file except in compliance with the License.
2660     * You may obtain a copy of the License at
2661     *
2662     *   http://www.apache.org/licenses/LICENSE-2.0
2663     *
2664     * Unless required by applicable law or agreed to in writing, software
2665     * distributed under the License is distributed on an "AS IS" BASIS,
2666     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2667     * See the License for the specific language governing permissions and
2668     * limitations under the License.
2669     */
2670    function bufferToBase64UrlSafe(array) {
2671        const b64 = btoa(String.fromCharCode(...array));
2672        return b64.replace(/\+/g, '-').replace(/\//g, '_');
2673    }
2674
2675    /**
2676     * @license
2677     * Copyright 2019 Google LLC
2678     *
2679     * Licensed under the Apache License, Version 2.0 (the "License");
2680     * you may not use this file except in compliance with the License.
2681     * You may obtain a copy of the License at
2682     *
2683     *   http://www.apache.org/licenses/LICENSE-2.0
2684     *
2685     * Unless required by applicable law or agreed to in writing, software
2686     * distributed under the License is distributed on an "AS IS" BASIS,
2687     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2688     * See the License for the specific language governing permissions and
2689     * limitations under the License.
2690     */
2691    const VALID_FID_PATTERN = /^[cdef][\w-]{21}$/;
2692    const INVALID_FID = '';
2693    /**
2694     * Generates a new FID using random values from Web Crypto API.
2695     * Returns an empty string if FID generation fails for any reason.
2696     */
2697    function generateFid() {
2698        try {
2699            // A valid FID has exactly 22 base64 characters, which is 132 bits, or 16.5
2700            // bytes. our implementation generates a 17 byte array instead.
2701            const fidByteArray = new Uint8Array(17);
2702            const crypto = self.crypto || self.msCrypto;
2703            crypto.getRandomValues(fidByteArray);
2704            // Replace the first 4 random bits with the constant FID header of 0b0111.
2705            fidByteArray[0] = 0b01110000 + (fidByteArray[0] % 0b00010000);
2706            const fid = encode(fidByteArray);
2707            return VALID_FID_PATTERN.test(fid) ? fid : INVALID_FID;
2708        }
2709        catch {
2710            // FID generation errored
2711            return INVALID_FID;
2712        }
2713    }
2714    /** Converts a FID Uint8Array to a base64 string representation. */
2715    function encode(fidByteArray) {
2716        const b64String = bufferToBase64UrlSafe(fidByteArray);
2717        // Remove the 23rd character that was added because of the extra 4 bits at the
2718        // end of our 17 byte array, and the '=' padding.
2719        return b64String.substr(0, 22);
2720    }
2721
2722    /**
2723     * @license
2724     * Copyright 2019 Google LLC
2725     *
2726     * Licensed under the Apache License, Version 2.0 (the "License");
2727     * you may not use this file except in compliance with the License.
2728     * You may obtain a copy of the License at
2729     *
2730     *   http://www.apache.org/licenses/LICENSE-2.0
2731     *
2732     * Unless required by applicable law or agreed to in writing, software
2733     * distributed under the License is distributed on an "AS IS" BASIS,
2734     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2735     * See the License for the specific language governing permissions and
2736     * limitations under the License.
2737     */
2738    /** Returns a string key that can be used to identify the app. */
2739    function getKey$1(appConfig) {
2740        return `${appConfig.appName}!${appConfig.appId}`;
2741    }
2742
2743    /**
2744     * @license
2745     * Copyright 2019 Google LLC
2746     *
2747     * Licensed under the Apache License, Version 2.0 (the "License");
2748     * you may not use this file except in compliance with the License.
2749     * You may obtain a copy of the License at
2750     *
2751     *   http://www.apache.org/licenses/LICENSE-2.0
2752     *
2753     * Unless required by applicable law or agreed to in writing, software
2754     * distributed under the License is distributed on an "AS IS" BASIS,
2755     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2756     * See the License for the specific language governing permissions and
2757     * limitations under the License.
2758     */
2759    const fidChangeCallbacks = new Map();
2760    /**
2761     * Calls the onIdChange callbacks with the new FID value, and broadcasts the
2762     * change to other tabs.
2763     */
2764    function fidChanged(appConfig, fid) {
2765        const key = getKey$1(appConfig);
2766        callFidChangeCallbacks(key, fid);
2767        broadcastFidChange(key, fid);
2768    }
2769    function callFidChangeCallbacks(key, fid) {
2770        const callbacks = fidChangeCallbacks.get(key);
2771        if (!callbacks) {
2772            return;
2773        }
2774        for (const callback of callbacks) {
2775            callback(fid);
2776        }
2777    }
2778    function broadcastFidChange(key, fid) {
2779        const channel = getBroadcastChannel();
2780        if (channel) {
2781            channel.postMessage({ key, fid });
2782        }
2783        closeBroadcastChannel();
2784    }
2785    let broadcastChannel = null;
2786    /** Opens and returns a BroadcastChannel if it is supported by the browser. */
2787    function getBroadcastChannel() {
2788        if (!broadcastChannel && 'BroadcastChannel' in self) {
2789            broadcastChannel = new BroadcastChannel('[Firebase] FID Change');
2790            broadcastChannel.onmessage = e => {
2791                callFidChangeCallbacks(e.data.key, e.data.fid);
2792            };
2793        }
2794        return broadcastChannel;
2795    }
2796    function closeBroadcastChannel() {
2797        if (fidChangeCallbacks.size === 0 && broadcastChannel) {
2798            broadcastChannel.close();
2799            broadcastChannel = null;
2800        }
2801    }
2802
2803    /**
2804     * @license
2805     * Copyright 2019 Google LLC
2806     *
2807     * Licensed under the Apache License, Version 2.0 (the "License");
2808     * you may not use this file except in compliance with the License.
2809     * You may obtain a copy of the License at
2810     *
2811     *   http://www.apache.org/licenses/LICENSE-2.0
2812     *
2813     * Unless required by applicable law or agreed to in writing, software
2814     * distributed under the License is distributed on an "AS IS" BASIS,
2815     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2816     * See the License for the specific language governing permissions and
2817     * limitations under the License.
2818     */
2819    const DATABASE_NAME$1 = 'firebase-installations-database';
2820    const DATABASE_VERSION$1 = 1;
2821    const OBJECT_STORE_NAME = 'firebase-installations-store';
2822    let dbPromise$1 = null;
2823    function getDbPromise$1() {
2824        if (!dbPromise$1) {
2825            dbPromise$1 = openDB(DATABASE_NAME$1, DATABASE_VERSION$1, {
2826                upgrade: (db, oldVersion) => {
2827                    // We don't use 'break' in this switch statement, the fall-through
2828                    // behavior is what we want, because if there are multiple versions between
2829                    // the old version and the current version, we want ALL the migrations
2830                    // that correspond to those versions to run, not only the last one.
2831                    // eslint-disable-next-line default-case
2832                    switch (oldVersion) {
2833                        case 0:
2834                            db.createObjectStore(OBJECT_STORE_NAME);
2835                    }
2836                }
2837            });
2838        }
2839        return dbPromise$1;
2840    }
vendor: 17,835 bytes, lines 2841-3264
2841    /** Assigns or overwrites the record for the given key with the given value. */
2842    async function set(appConfig, value) {
2843        const key = getKey$1(appConfig);
2844        const db = await getDbPromise$1();
2845        const tx = db.transaction(OBJECT_STORE_NAME, 'readwrite');
2846        const objectStore = tx.objectStore(OBJECT_STORE_NAME);
2847        const oldValue = (await objectStore.get(key));
2848        await objectStore.put(value, key);
2849        await tx.done;
2850        if (!oldValue || oldValue.fid !== value.fid) {
2851            fidChanged(appConfig, value.fid);
2852        }
2853        return value;
2854    }
2855    /** Removes record(s) from the objectStore that match the given key. */
2856    async function remove(appConfig) {
2857        const key = getKey$1(appConfig);
2858        const db = await getDbPromise$1();
2859        const tx = db.transaction(OBJECT_STORE_NAME, 'readwrite');
2860        await tx.objectStore(OBJECT_STORE_NAME).delete(key);
2861        await tx.done;
2862    }
2863    /**
2864     * Atomically updates a record with the result of updateFn, which gets
2865     * called with the current value. If newValue is undefined, the record is
2866     * deleted instead.
2867     * @return Updated value
2868     */
2869    async function update(appConfig, updateFn) {
2870        const key = getKey$1(appConfig);
2871        const db = await getDbPromise$1();
2872        const tx = db.transaction(OBJECT_STORE_NAME, 'readwrite');
2873        const store = tx.objectStore(OBJECT_STORE_NAME);
2874        const oldValue = (await store.get(key));
2875        const newValue = updateFn(oldValue);
2876        if (newValue === undefined) {
2877            await store.delete(key);
2878        }
2879        else {
2880            await store.put(newValue, key);
2881        }
2882        await tx.done;
2883        if (newValue && (!oldValue || oldValue.fid !== newValue.fid)) {
2884            fidChanged(appConfig, newValue.fid);
2885        }
2886        return newValue;
2887    }
2888
2889    /**
2890     * @license
2891     * Copyright 2019 Google LLC
2892     *
2893     * Licensed under the Apache License, Version 2.0 (the "License");
2894     * you may not use this file except in compliance with the License.
2895     * You may obtain a copy of the License at
2896     *
2897     *   http://www.apache.org/licenses/LICENSE-2.0
2898     *
2899     * Unless required by applicable law or agreed to in writing, software
2900     * distributed under the License is distributed on an "AS IS" BASIS,
2901     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2902     * See the License for the specific language governing permissions and
2903     * limitations under the License.
2904     */
2905    /**
2906     * Updates and returns the InstallationEntry from the database.
2907     * Also triggers a registration request if it is necessary and possible.
2908     */
2909    async function getInstallationEntry(installations) {
2910        let registrationPromise;
2911        const installationEntry = await update(installations.appConfig, oldEntry => {
2912            const installationEntry = updateOrCreateInstallationEntry(oldEntry);
2913            const entryWithPromise = triggerRegistrationIfNecessary(installations, installationEntry);
2914            registrationPromise = entryWithPromise.registrationPromise;
2915            return entryWithPromise.installationEntry;
2916        });
2917        if (installationEntry.fid === INVALID_FID) {
2918            // FID generation failed. Waiting for the FID from the server.
2919            return { installationEntry: await registrationPromise };
2920        }
2921        return {
2922            installationEntry,
2923            registrationPromise
2924        };
2925    }
2926    /**
2927     * Creates a new Installation Entry if one does not exist.
2928     * Also clears timed out pending requests.
2929     */
2930    function updateOrCreateInstallationEntry(oldEntry) {
2931        const entry = oldEntry || {
2932            fid: generateFid(),
2933            registrationStatus: 0 /* RequestStatus.NOT_STARTED */
2934        };
2935        return clearTimedOutRequest(entry);
2936    }
2937    /**
2938     * If the Firebase Installation is not registered yet, this will trigger the
2939     * registration and return an InProgressInstallationEntry.
2940     *
2941     * If registrationPromise does not exist, the installationEntry is guaranteed
2942     * to be registered.
2943     */
2944    function triggerRegistrationIfNecessary(installations, installationEntry) {
2945        if (installationEntry.registrationStatus === 0 /* RequestStatus.NOT_STARTED */) {
2946            if (!navigator.onLine) {
2947                // Registration required but app is offline.
2948                const registrationPromiseWithError = Promise.reject(ERROR_FACTORY$1.create("app-offline" /* ErrorCode.APP_OFFLINE */));
2949                return {
2950                    installationEntry,
2951                    registrationPromise: registrationPromiseWithError
2952                };
2953            }
2954            // Try registering. Change status to IN_PROGRESS.
2955            const inProgressEntry = {
2956                fid: installationEntry.fid,
2957                registrationStatus: 1 /* RequestStatus.IN_PROGRESS */,
2958                registrationTime: Date.now()
2959            };
2960            const registrationPromise = registerInstallation(installations, inProgressEntry);
2961            return { installationEntry: inProgressEntry, registrationPromise };
2962        }
2963        else if (installationEntry.registrationStatus === 1 /* RequestStatus.IN_PROGRESS */) {
2964            return {
2965                installationEntry,
2966                registrationPromise: waitUntilFidRegistration(installations)
2967            };
2968        }
2969        else {
2970            return { installationEntry };
2971        }
2972    }
2973    /** This will be executed only once for each new Firebase Installation. */
2974    async function registerInstallation(installations, installationEntry) {
2975        try {
2976            const registeredInstallationEntry = await createInstallationRequest(installations, installationEntry);
2977            return set(installations.appConfig, registeredInstallationEntry);
2978        }
2979        catch (e) {
2980            if (isServerError(e) && e.customData.serverCode === 409) {
2981                // Server returned a "FID cannot be used" error.
2982                // Generate a new ID next time.
2983                await remove(installations.appConfig);
2984            }
2985            else {
2986                // Registration failed. Set FID as not registered.
2987                await set(installations.appConfig, {
2988                    fid: installationEntry.fid,
2989                    registrationStatus: 0 /* RequestStatus.NOT_STARTED */
2990                });
2991            }
2992            throw e;
2993        }
2994    }
2995    /** Call if FID registration is pending in another request. */
2996    async function waitUntilFidRegistration(installations) {
2997        // Unfortunately, there is no way of reliably observing when a value in
2998        // IndexedDB changes (yet, see https://github.com/WICG/indexed-db-observers),
2999        // so we need to poll.
3000        let entry = await updateInstallationRequest(installations.appConfig);
3001        while (entry.registrationStatus === 1 /* RequestStatus.IN_PROGRESS */) {
3002            // createInstallation request still in progress.
3003            await sleep$1(100);
3004            entry = await updateInstallationRequest(installations.appConfig);
3005        }
3006        if (entry.registrationStatus === 0 /* RequestStatus.NOT_STARTED */) {
3007            // The request timed out or failed in a different call. Try again.
3008            const { installationEntry, registrationPromise } = await getInstallationEntry(installations);
3009            if (registrationPromise) {
3010                return registrationPromise;
3011            }
3012            else {
3013                // if there is no registrationPromise, entry is registered.
3014                return installationEntry;
3015            }
3016        }
3017        return entry;
3018    }
3019    /**
3020     * Called only if there is a CreateInstallation request in progress.
3021     *
3022     * Updates the InstallationEntry in the DB based on the status of the
3023     * CreateInstallation request.
3024     *
3025     * Returns the updated InstallationEntry.
3026     */
3027    function updateInstallationRequest(appConfig) {
3028        return update(appConfig, oldEntry => {
3029            if (!oldEntry) {
3030                throw ERROR_FACTORY$1.create("installation-not-found" /* ErrorCode.INSTALLATION_NOT_FOUND */);
3031            }
3032            return clearTimedOutRequest(oldEntry);
3033        });
3034    }
3035    function clearTimedOutRequest(entry) {
3036        if (hasInstallationRequestTimedOut(entry)) {
3037            return {
3038                fid: entry.fid,
3039                registrationStatus: 0 /* RequestStatus.NOT_STARTED */
3040            };
3041        }
3042        return entry;
3043    }
3044    function hasInstallationRequestTimedOut(installationEntry) {
3045        return (installationEntry.registrationStatus === 1 /* RequestStatus.IN_PROGRESS */ &&
3046            installationEntry.registrationTime + PENDING_TIMEOUT_MS < Date.now());
3047    }
3048
3049    /**
3050     * @license
3051     * Copyright 2019 Google LLC
3052     *
3053     * Licensed under the Apache License, Version 2.0 (the "License");
3054     * you may not use this file except in compliance with the License.
3055     * You may obtain a copy of the License at
3056     *
3057     *   http://www.apache.org/licenses/LICENSE-2.0
3058     *
3059     * Unless required by applicable law or agreed to in writing, software
3060     * distributed under the License is distributed on an "AS IS" BASIS,
3061     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
3062     * See the License for the specific language governing permissions and
3063     * limitations under the License.
3064     */
3065    async function generateAuthTokenRequest({ appConfig, heartbeatServiceProvider }, installationEntry) {
3066        const endpoint = getGenerateAuthTokenEndpoint(appConfig, installationEntry);
3067        const headers = getHeadersWithAuth(appConfig, installationEntry);
3068        // If heartbeat service exists, add the heartbeat string to the header.
3069        const heartbeatService = heartbeatServiceProvider.getImmediate({
3070            optional: true
3071        });
3072        if (heartbeatService) {
3073            const heartbeatsHeader = await heartbeatService.getHeartbeatsHeader();
3074            if (heartbeatsHeader) {
3075                headers.append('x-firebase-client', heartbeatsHeader);
3076            }
3077        }
3078        const body = {
3079            installation: {
3080                sdkVersion: PACKAGE_VERSION,
3081                appId: appConfig.appId
3082            }
3083        };
3084        const request = {
3085            method: 'POST',
3086            headers,
3087            body: JSON.stringify(body)
3088        };
3089        const response = await retryIfServerError(() => fetch(endpoint, request));
3090        if (response.ok) {
3091            const responseValue = await response.json();
3092            const completedAuthToken = extractAuthTokenInfoFromResponse(responseValue);
3093            return completedAuthToken;
3094        }
3095        else {
3096            throw await getErrorFromResponse('Generate Auth Token', response);
3097        }
3098    }
3099    function getGenerateAuthTokenEndpoint(appConfig, { fid }) {
3100        return `${getInstallationsEndpoint(appConfig)}/${fid}/authTokens:generate`;
3101    }
3102
3103    /**
3104     * @license
3105     * Copyright 2019 Google LLC
3106     *
3107     * Licensed under the Apache License, Version 2.0 (the "License");
3108     * you may not use this file except in compliance with the License.
3109     * You may obtain a copy of the License at
3110     *
3111     *   http://www.apache.org/licenses/LICENSE-2.0
3112     *
3113     * Unless required by applicable law or agreed to in writing, software
3114     * distributed under the License is distributed on an "AS IS" BASIS,
3115     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
3116     * See the License for the specific language governing permissions and
3117     * limitations under the License.
3118     */
3119    /**
3120     * Returns a valid authentication token for the installation. Generates a new
3121     * token if one doesn't exist, is expired or about to expire.
3122     *
3123     * Should only be called if the Firebase Installation is registered.
3124     */
3125    async function refreshAuthToken(installations, forceRefresh = false) {
3126        let tokenPromise;
3127        const entry = await update(installations.appConfig, oldEntry => {
3128            if (!isEntryRegistered(oldEntry)) {
3129                throw ERROR_FACTORY$1.create("not-registered" /* ErrorCode.NOT_REGISTERED */);
3130            }
3131            const oldAuthToken = oldEntry.authToken;
3132            if (!forceRefresh && isAuthTokenValid(oldAuthToken)) {
3133                // There is a valid token in the DB.
3134                return oldEntry;
3135            }
3136            else if (oldAuthToken.requestStatus === 1 /* RequestStatus.IN_PROGRESS */) {
3137                // There already is a token request in progress.
3138                tokenPromise = waitUntilAuthTokenRequest(installations, forceRefresh);
3139                return oldEntry;
3140            }
3141            else {
3142                // No token or token expired.
3143                if (!navigator.onLine) {
3144                    throw ERROR_FACTORY$1.create("app-offline" /* ErrorCode.APP_OFFLINE */);
3145                }
3146                const inProgressEntry = makeAuthTokenRequestInProgressEntry(oldEntry);
3147                tokenPromise = fetchAuthTokenFromServer(installations, inProgressEntry);
3148                return inProgressEntry;
3149            }
3150        });
3151        const authToken = tokenPromise
3152            ? await tokenPromise
3153            : entry.authToken;
3154        return authToken;
3155    }
3156    /**
3157     * Call only if FID is registered and Auth Token request is in progress.
3158     *
3159     * Waits until the current pending request finishes. If the request times out,
3160     * tries once in this thread as well.
3161     */
3162    async function waitUntilAuthTokenRequest(installations, forceRefresh) {
3163        // Unfortunately, there is no way of reliably observing when a value in
3164        // IndexedDB changes (yet, see https://github.com/WICG/indexed-db-observers),
3165        // so we need to poll.
3166        let entry = await updateAuthTokenRequest(installations.appConfig);
3167        while (entry.authToken.requestStatus === 1 /* RequestStatus.IN_PROGRESS */) {
3168            // generateAuthToken still in progress.
3169            await sleep$1(100);
3170            entry = await updateAuthTokenRequest(installations.appConfig);
3171        }
3172        const authToken = entry.authToken;
3173        if (authToken.requestStatus === 0 /* RequestStatus.NOT_STARTED */) {
3174            // The request timed out or failed in a different call. Try again.
3175            return refreshAuthToken(installations, forceRefresh);
3176        }
3177        else {
3178            return authToken;
3179        }
3180    }
3181    /**
3182     * Called only if there is a GenerateAuthToken request in progress.
3183     *
3184     * Updates the InstallationEntry in the DB based on the status of the
3185     * GenerateAuthToken request.
3186     *
3187     * Returns the updated InstallationEntry.
3188     */
3189    function updateAuthTokenRequest(appConfig) {
3190        return update(appConfig, oldEntry => {
3191            if (!isEntryRegistered(oldEntry)) {
3192                throw ERROR_FACTORY$1.create("not-registered" /* ErrorCode.NOT_REGISTERED */);
3193            }
3194            const oldAuthToken = oldEntry.authToken;
3195            if (hasAuthTokenRequestTimedOut(oldAuthToken)) {
3196                return {
3197                    ...oldEntry,
3198                    authToken: { requestStatus: 0 /* RequestStatus.NOT_STARTED */ }
3199                };
3200            }
3201            return oldEntry;
3202        });
3203    }
3204    async function fetchAuthTokenFromServer(installations, installationEntry) {
3205        try {
3206            const authToken = await generateAuthTokenRequest(installations, installationEntry);
3207            const updatedInstallationEntry = {
3208                ...installationEntry,
3209                authToken
3210            };
3211            await set(installations.appConfig, updatedInstallationEntry);
3212            return authToken;
3213        }
3214        catch (e) {
3215            if (isServerError(e) &&
3216                (e.customData.serverCode === 401 || e.customData.serverCode === 404)) {
3217                // Server returned a "FID not found" or a "Invalid authentication" error.
3218                // Generate a new ID next time.
3219                await remove(installations.appConfig);
3220            }
3221            else {
3222                const updatedInstallationEntry = {
3223                    ...installationEntry,
3224                    authToken: { requestStatus: 0 /* RequestStatus.NOT_STARTED */ }
3225                };
3226                await set(installations.appConfig, updatedInstallationEntry);
3227            }
3228            throw e;
3229        }
3230    }
3231    function isEntryRegistered(installationEntry) {
3232        return (installationEntry !== undefined &&
3233            installationEntry.registrationStatus === 2 /* RequestStatus.COMPLETED */);
3234    }
3235    function isAuthTokenValid(authToken) {
3236        return (authToken.requestStatus === 2 /* RequestStatus.COMPLETED */ &&
3237            !isAuthTokenExpired(authToken));
3238    }
3239    function isAuthTokenExpired(authToken) {
3240        const now = Date.now();
3241        return (now < authToken.creationTime ||
3242            authToken.creationTime + authToken.expiresIn < now + TOKEN_EXPIRATION_BUFFER);
3243    }
3244    /** Returns an updated InstallationEntry with an InProgressAuthToken. */
3245    function makeAuthTokenRequestInProgressEntry(oldEntry) {
3246        const inProgressAuthToken = {
3247            requestStatus: 1 /* RequestStatus.IN_PROGRESS */,
3248            requestTime: Date.now()
3249        };
3250        return {
3251            ...oldEntry,
3252            authToken: inProgressAuthToken
3253        };
3254    }
3255    function hasAuthTokenRequestTimedOut(authToken) {
3256        return (authToken.requestStatus === 1 /* RequestStatus.IN_PROGRESS */ &&
3257            authToken.requestTime + PENDING_TIMEOUT_MS < Date.now());
3258    }
3259
3260    /**
3261     * @license
3262     * Copyright 2019 Google LLC
3263     *
3264     * Licensed under the Apache License, Version 2.0 (the "License");
3265     * you may not use this file except in compliance with the License.
3266     * You may obtain a copy of the License at
3267     *
3268     *   http://www.apache.org/licenses/LICENSE-2.0
3269     *
3270     * Unless required by applicable law or agreed to in writing, software
3271     * distributed under the License is distributed on an "AS IS" BASIS,
3272     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
3273     * See the License for the specific language governing permissions and
3274     * limitations under the License.
3275     */
3276    /**
3277     * Creates a Firebase Installation if there isn't one for the app and
3278     * returns the Installation ID.
3279     * @param installations - The `Installations` instance.
3280     *
3281     * @public
3282     */
3283    async function getId(installations) {
3284        const installationsImpl = installations;
3285        const { installationEntry, registrationPromise } = await getInstallationEntry(installationsImpl);
3286        if (registrationPromise) {
3287            registrationPromise.catch(console.error);
3288        }
3289        else {
3290            // If the installation is already registered, update the authentication
3291            // token if needed.
3292            refreshAuthToken(installationsImpl).catch(console.error);
3293        }
3294        return installationEntry.fid;
3295    }
3296
3297    /**
3298     * @license
3299     * Copyright 2019 Google LLC
3300     *
3301     * Licensed under the Apache License, Version 2.0 (the "License");
3302     * you may not use this file except in compliance with the License.
3303     * You may obtain a copy of the License at
3304     *
3305     *   http://www.apache.org/licenses/LICENSE-2.0
3306     *
3307     * Unless required by applicable law or agreed to in writing, software
3308     * distributed under the License is distributed on an "AS IS" BASIS,
3309     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
3310     * See the License for the specific language governing permissions and
3311     * limitations under the License.
3312     */
3313    /**
3314     * Returns a Firebase Installations auth token, identifying the current
3315     * Firebase Installation.
3316     * @param installations - The `Installations` instance.
3317     * @param forceRefresh - Force refresh regardless of token expiration.
3318     *
3319     * @public
3320     */
3321    async function getToken(installations, forceRefresh = false) {
3322        const installationsImpl = installations;
3323        await completeInstallationRegistration(installationsImpl);
3324        // At this point we either have a Registered Installation in the DB, or we've
3325        // already thrown an error.
3326        const authToken = await refreshAuthToken(installationsImpl, forceRefresh);
3327        return authToken.token;
3328    }
3329    async function completeInstallationRegistration(installations) {
3330        const { registrationPromise } = await getInstallationEntry(installations);
3331        if (registrationPromise) {
3332            // A createInstallation request is in progress. Wait until it finishes.
3333            await registrationPromise;
3334        }
3335    }
3336
3337    /**
3338     * @license
3339     * Copyright 2019 Google LLC
3340     *
3341     * Licensed under the Apache License, Version 2.0 (the "License");
3342     * you may not use this file except in compliance with the License.
3343     * You may obtain a copy of the License at
3344     *
3345     *   http://www.apache.org/licenses/LICENSE-2.0
3346     *
3347     * Unless required by applicable law or agreed to in writing, software
3348     * distributed under the License is distributed on an "AS IS" BASIS,
3349     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
3350     * See the License for the specific language governing permissions and
3351     * limitations under the License.
3352     */
3353    function extractAppConfig$1(app) {
3354        if (!app || !app.options) {
3355            throw getMissingValueError$1('App Configuration');
3356        }
3357        if (!app.name) {
3358            throw getMissingValueError$1('App Name');
3359        }
3360        // Required app config keys
3361        const configKeys = [
3362            'projectId',
3363            'apiKey',
3364            'appId'
3365        ];
3366        for (const keyName of configKeys) {
3367            if (!app.options[keyName]) {
3368                throw getMissingValueError$1(keyName);
3369            }
3370        }
3371        return {
3372            appName: app.name,
3373            projectId: app.options.projectId,
3374            apiKey: app.options.apiKey,
3375            appId: app.options.appId
3376        };
3377    }
3378    function getMissingValueError$1(valueName) {
3379        return ERROR_FACTORY$1.create("missing-app-config-values" /* ErrorCode.MISSING_APP_CONFIG_VALUES */, {
3380            valueName
3381        });
3382    }
3383
3384    /**
3385     * @license
3386     * Copyright 2020 Google LLC
3387     *
3388     * Licensed under the Apache License, Version 2.0 (the "License");
3389     * you may not use this file except in compliance with the License.
3390     * You may obtain a copy of the License at
3391     *
3392     *   http://www.apache.org/licenses/LICENSE-2.0
3393     *
3394     * Unless required by applicable law or agreed to in writing, software
3395     * distributed under the License is distributed on an "AS IS" BASIS,
3396     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
3397     * See the License for the specific language governing permissions and
3398     * limitations under the License.
3399     */
3400    const INSTALLATIONS_NAME = 'installations';
3401    const INSTALLATIONS_NAME_INTERNAL = 'installations-internal';
3402    const publicFactory = (container) => {
3403        const app = container.getProvider('app').getImmediate();
3404        // Throws if app isn't configured properly.
3405        const appConfig = extractAppConfig$1(app);
3406        const heartbeatServiceProvider = _getProvider(app, 'heartbeat');
3407        const installationsImpl = {
3408            app,
3409            appConfig,
3410            heartbeatServiceProvider,
3411            _delete: () => Promise.resolve()
3412        };
3413        return installationsImpl;
3414    };
3415    const internalFactory = (container) => {
3416        const app = container.getProvider('app').getImmediate();
3417        // Internal FIS instance relies on public FIS instance.
3418        const installations = _getProvider(app, INSTALLATIONS_NAME).getImmediate();
3419        const installationsInternal = {
3420            getId: () => getId(installations),
3421            getToken: (forceRefresh) => getToken(installations, forceRefresh)
3422        };
3423        return installationsInternal;
3424    };
3425    function registerInstallations() {
3426        _registerComponent(new Component(INSTALLATIONS_NAME, publicFactory, "PUBLIC" /* ComponentType.PUBLIC */));
3427        _registerComponent(new Component(INSTALLATIONS_NAME_INTERNAL, internalFactory, "PRIVATE" /* ComponentType.PRIVATE */));
3428    }
3429
3430    /**
3431     * The Firebase Installations Web SDK.
3432     * This SDK does not work in a Node.js environment.
3433     *
3434     * @packageDocumentation
3435     */
3436    registerInstallations();
3437    registerVersion(name, version$1);
3438    // BUILD_TARGET will be replaced by values like esm, cjs, etc during the compilation
3439    registerVersion(name, version$1, 'esm2020');
3440
3441    /**
3442     * @license
3443     * Copyright 2019 Google LLC
3444     *
3445     * Licensed under the Apache License, Version 2.0 (the "License");
3446     * you may not use this file except in compliance with the License.
3447     * You may obtain a copy of the License at
3448     *
3449     *   http://www.apache.org/licenses/LICENSE-2.0
3450     *
3451     * Unless required by applicable law or agreed to in writing, software
3452     * distributed under the License is distributed on an "AS IS" BASIS,
3453     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
3454     * See the License for the specific language governing permissions and
3455     * limitations under the License.
3456     */
3457    const DEFAULT_VAPID_KEY = 'BDOU99-h67HcA6JeFXHbSNMu7e2yNNu3RzoMj8TM4W88jITfq7ZmPvIM1Iv-4_l2LxQcYwhqby2xGpWwzjfAnG4';
3458    const ENDPOINT = 'https://fcmregistrations.googleapis.com/v1';
3459    /** Key of FCM Payload in Notification's data field. */
3460    const FCM_MSG = 'FCM_MSG';
3461    const CONSOLE_CAMPAIGN_ID = 'google.c.a.c_id';
3462    const MAX_NUMBER_OF_EVENTS_PER_LOG_REQUEST = 1000;
3463    const MAX_RETRIES = 3;
3464    const LOG_INTERVAL_IN_MS = 86400000; //24 hour
3465    const DEFAULT_BACKOFF_TIME_MS = 5000;
3466    // FCM log source name registered at Firelog: 'FCM_CLIENT_EVENT_LOGGING'. It uniquely identifies
3467    // FCM's logging configuration.
3468    const FCM_LOG_SOURCE = 1249;
3469    // Defined as in proto/messaging_event.proto. Neglecting fields that are supported.
3470    const SDK_PLATFORM_WEB = 3;
3471    const EVENT_MESSAGE_DELIVERED = 1;
3472    var MessageType$1;
3473    (function (MessageType) {
3474        MessageType[MessageType["DATA_MESSAGE"] = 1] = "DATA_MESSAGE";
3475        MessageType[MessageType["DISPLAY_NOTIFICATION"] = 3] = "DISPLAY_NOTIFICATION";
3476    })(MessageType$1 || (MessageType$1 = {}));
3477
3478    /**
3479     * @license
3480     * Copyright 2018 Google LLC
3481     *
3482     * Licensed under the Apache License, Version 2.0 (the "License");
3482 you may not use this file except
3483     * in compliance with the License. You may obtain a copy of the License at
3484     *
3485     * http://www.apache.org/licenses/LICENSE-2.0
3486     *
3487     * Unless required by applicable law or agreed to in writing, software distributed under the License
3488     * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
3489     * or implied. See the License for the specific language governing permissions and limitations under
3490     * the License.
3491     */
3492    var MessageType;
3493    (function (MessageType) {
3494        MessageType["PUSH_RECEIVED"] = "push-received";
3495        MessageType["NOTIFICATION_CLICKED"] = "notification-clicked";
3496        MessageType["FID_REGISTERED"] = "fid-registered";
3497    })(MessageType || (MessageType = {}));
3498
3499    /**
3500     * @license
3501     * Copyright 2017 Google LLC
3502     *
3503     * Licensed under the Apache License, Version 2.0 (the "License");
3504     * you may not use this file except in compliance with the License.
3505     * You may obtain a copy of the License at
3506     *
3507     *   http://www.apache.org/licenses/LICENSE-2.0
3508     *
3509     * Unless required by applicable law or agreed to in writing, software
3510     * distributed under the License is distributed on an "AS IS" BASIS,
3511     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
3512     * See the License for the specific language governing permissions and
3513     * limitations under the License.
3514     */
3515    function arrayToBase64(array) {
3516        const uint8Array = new Uint8Array(array);
3517        const base64String = btoa(String.fromCharCode(...uint8Array));
3518        return base64String.replace(/=/g, '').replace(/\+/g, '-').replace(/\//g, '_');
3519    }
3520    function base64ToArray(base64String) {
3521        const padding = '='.repeat((4 - (base64String.length % 4)) % 4);
3522        const base64 = (base64String + padding)
3523            .replace(/\-/g, '+')
3524            .replace(/_/g, '/');
3525        const rawData = atob(base64);
3526        const outputArray = new Uint8Array(rawData.length);
3527        for (let i = 0; i < rawData.length; ++i) {
3528            outputArray[i] = rawData.charCodeAt(i);
3529        }
3530        return outputArray;
3531    }
3532
3533    /**
3534     * @license
3535     * Copyright 2019 Google LLC
3536     *
3537     * Licensed under the Apache License, Version 2.0 (the "License");
3538     * you may not use this file except in compliance with the License.
3539     * You may obtain a copy of the License at
3540     *
3541     *   http://www.apache.org/licenses/LICENSE-2.0
3542     *
3543     * Unless required by applicable law or agreed to in writing, software
3544     * distributed under the License is distributed on an "AS IS" BASIS,
3545     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
3546     * See the License for the specific language governing permissions and
3547     * limitations under the License.
3548     */
3549    const OLD_DB_NAME = 'fcm_token_details_db';
3550    /**
3551     * The last DB version of 'fcm_token_details_db' was 4. This is one higher, so that the upgrade
3552     * callback is called for all versions of the old DB.
3553     */
3554    const OLD_DB_VERSION = 5;
3555    const OLD_OBJECT_STORE_NAME = 'fcm_token_object_Store';
3556    async function migrateOldDatabase(senderId) {
3557        if ('databases' in indexedDB) {
3558            // indexedDb.databases() is an IndexedDB v3 API and does not exist in all browsers. TODO: Remove
3559            // typecast when it lands in TS types.
3560            const databases = await indexedDB.databases();
3561            const dbNames = databases.map(db => db.name);
3562            if (!dbNames.includes(OLD_DB_NAME)) {
3563                // old DB didn't exist, no need to open.
3564                return null;
3565            }
3566        }
3567        let tokenDetails = null;
3568        const db = await openDB(OLD_DB_NAME, OLD_DB_VERSION, {
3569            upgrade: async (db, oldVersion, newVersion, upgradeTransaction) => {
3570                if (oldVersion < 2) {
3571                    // Database too old, skip migration.
3572                    return;
3573                }
3574                if (!db.objectStoreNames.contains(OLD_OBJECT_STORE_NAME)) {
3575                    // Database did not exist. Nothing to do.
3576                    return;
3577                }
3578                const objectStore = upgradeTransaction.objectStore(OLD_OBJECT_STORE_NAME);
3579                const value = await objectStore.index('fcmSenderId').get(senderId);
3580                await objectStore.clear();
3581                if (!value) {
3582                    // No entry in the database, nothing to migrate.
3583                    return;
3584                }
3585                if (oldVersion === 2) {
3586                    const oldDetails = value;
3587                    if (!oldDetails.auth || !oldDetails.p256dh || !oldDetails.endpoint) {
3588                        return;
3589                    }
3590                    tokenDetails = {
3591                        token: oldDetails.fcmToken,
3592                        createTime: oldDetails.createTime ?? Date.now(),
3593                        subscriptionOptions: {
3594                            auth: oldDetails.auth,
3595                            p256dh: oldDetails.p256dh,
3596                            endpoint: oldDetails.endpoint,
3597                            swScope: oldDetails.swScope,
3598                            vapidKey: typeof oldDetails.vapidKey === 'string'
3599                                ? oldDetails.vapidKey
3600                                : arrayToBase64(oldDetails.vapidKey)
3601                        }
3602                    };
3603                }
3604                else if (oldVersion === 3) {
3605                    const oldDetails = value;
3606                    tokenDetails = {
3607                        token: oldDetails.fcmToken,
3608                        createTime: oldDetails.createTime,
3609                        subscriptionOptions: {
3610                            auth: arrayToBase64(oldDetails.auth),
3611                            p256dh: arrayToBase64(oldDetails.p256dh),
3612                            endpoint: oldDetails.endpoint,
3613                            swScope: oldDetails.swScope,
3614                            vapidKey: arrayToBase64(oldDetails.vapidKey)
3615                        }
3616                    };
3617                }
3618                else if (oldVersion === 4) {
3619                    const oldDetails = value;
3620                    tokenDetails = {
3621                        token: oldDetails.fcmToken,
3622                        createTime: oldDetails.createTime,
3623                        subscriptionOptions: {
3624                            auth: arrayToBase64(oldDetails.auth),
3625                            p256dh: arrayToBase64(oldDetails.p256dh),
3626                            endpoint: oldDetails.endpoint,
3627                            swScope: oldDetails.swScope,
3628                            vapidKey: arrayToBase64(oldDetails.vapidKey)
3629                        }
3630                    };
3631                }
3632            }
3633        });
3634        db.close();
3635        // Delete all old databases.
3636        await deleteDB(OLD_DB_NAME);
3637        await deleteDB('fcm_vapid_details_db');
3638        await deleteDB('undefined');
3639        return checkTokenDetails(tokenDetails) ? tokenDetails : null;
3640    }
3641    function checkTokenDetails(tokenDetails) {
3642        if (!tokenDetails || !tokenDetails.subscriptionOptions) {
3643            return false;
3644        }
3645        const { subscriptionOptions } = tokenDetails;
3646        return (typeof tokenDetails.createTime === 'number' &&
3647            tokenDetails.createTime > 0 &&
3648            typeof tokenDetails.token === 'string' &&
3649            tokenDetails.token.length > 0 &&
3650            typeof subscriptionOptions.auth === 'string' &&
3651            subscriptionOptions.auth.length > 0 &&
3652            typeof subscriptionOptions.p256dh === 'string' &&
3653            subscriptionOptions.p256dh.length > 0 &&
3654            typeof subscriptionOptions.endpoint === 'string' &&
3655            subscriptionOptions.endpoint.length > 0 &&
3656            typeof subscriptionOptions.swScope === 'string' &&
3657            subscriptionOptions.swScope.length > 0 &&
3658            typeof subscriptionOptions.vapidKey === 'string' &&
3659            subscriptionOptions.vapidKey.length > 0);
3660    }
3661
3662    /**
3663     * @license
3664     * Copyright 2017 Google LLC
3665     *
3666     * Licensed under the Apache License, Version 2.0 (the "License");
3667     * you may not use this file except in compliance with the License.
3668     * You may obtain a copy of the License at
3669     *
3670     *   http://www.apache.org/licenses/LICENSE-2.0
3671     *
3672     * Unless required by applicable law or agreed to in writing, software
3673     * distributed under the License is distributed on an "AS IS" BASIS,
3674     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
3675     * See the License for the specific language governing permissions and
3676     * limitations under the License.
3677     */
3678    const ERROR_MAP = {
3679        ["missing-app-config-values" /* ErrorCode.MISSING_APP_CONFIG_VALUES */]: 'Missing App configuration value: "{$valueName}"',
3680        ["only-available-in-window" /* ErrorCode.AVAILABLE_IN_WINDOW */]: 'This method is available in a Window context.',
3681        ["only-available-in-sw" /* ErrorCode.AVAILABLE_IN_SW */]: 'This method is available in a service worker context.',
3682        ["permission-default" /* ErrorCode.PERMISSION_DEFAULT */]: 'The notification permission was not granted and dismissed instead.',
3683        ["permission-blocked" /* ErrorCode.PERMISSION_BLOCKED */]: 'The notification permission was not granted and blocked instead.',
3684        ["unsupported-browser" /* ErrorCode.UNSUPPORTED_BROWSER */]: "This browser doesn't support the API's required to use the Firebase SDK.",
3685        ["indexed-db-unsupported" /* ErrorCode.INDEXED_DB_UNSUPPORTED */]: "This browser doesn't support indexedDb.open() (ex. Safari iFrame, Firefox Private Browsing, etc)",
3686        ["failed-service-worker-registration" /* ErrorCode.FAILED_DEFAULT_REGISTRATION */]: 'We are unable to register the default service worker. {$browserErrorMessage}',
3687        ["token-subscribe-failed" /* ErrorCode.TOKEN_SUBSCRIBE_FAILED */]: 'A problem occurred while subscribing the user to FCM: {$errorInfo}',
3688        ["token-subscribe-no-token" /* ErrorCode.TOKEN_SUBSCRIBE_NO_TOKEN */]: 'FCM returned no token when subscribing the user to push.',
3689        ["fid-registration-failed" /* ErrorCode.FID_REGISTRATION_FAILED */]: 'A problem occurred while creating an FCM registration via FID: {$errorInfo}',
3690        ["fid-unregister-failed" /* ErrorCode.FID_UNREGISTER_FAILED */]: 'A problem occurred while unregistering the FCM registration via FID: {$errorInfo}',
3691        ["fid-registration-idb-schema-unavailable" /* ErrorCode.FID_REGISTRATION_IDB_SCHEMA_UNAVAILABLE */]: 'Unable to read or persist FID registration metadata because the messaging ' +
3692            'IndexedDB schema is unavailable (for example, the database could not be ' +
3693            'upgraded to the latest version).',
3694        ["token-unsubscribe-failed" /* ErrorCode.TOKEN_UNSUBSCRIBE_FAILED */]: 'A problem occurred while unsubscribing the ' +
3695            'user from FCM: {$errorInfo}',
3696        ["token-update-failed" /* ErrorCode.TOKEN_UPDATE_FAILED */]: 'A problem occurred while updating the user from FCM: {$errorInfo}',
3697        ["token-update-no-token" /* ErrorCode.TOKEN_UPDATE_NO_TOKEN */]: 'FCM returned no token when updating the user to push.',
3698        ["use-sw-after-get-token" /* ErrorCode.USE_SW_AFTER_GET_TOKEN */]: 'The useServiceWorker() method may only be called once and must be ' +
3699            'called before calling getToken() to ensure your service worker is used.',
vendor: 11,649 bytes, lines 3700-3957
3700        ["invalid-sw-registration" /* ErrorCode.INVALID_SW_REGISTRATION */]: 'The input to useServiceWorker() must be a ServiceWorkerRegistration.',
3701        ["invalid-bg-handler" /* ErrorCode.INVALID_BG_HANDLER */]: 'The input to setBackgroundMessageHandler() must be a function.',
3702        ["invalid-vapid-key" /* ErrorCode.INVALID_VAPID_KEY */]: 'The public VAPID key must be a string.',
3703        ["use-vapid-key-after-get-token" /* ErrorCode.USE_VAPID_KEY_AFTER_GET_TOKEN */]: 'The usePublicVapidKey() method may only be called once and must be ' +
3704            'called before calling getToken() to ensure your VAPID key is used.',
3705        ["invalid-on-registered-handler" /* ErrorCode.INVALID_ON_REGISTERED_HANDLER */]: 'No onRegistered callback handler was provided or registered. Implement onRegistered() before register().'
3706    };
3707    const ERROR_FACTORY = new ErrorFactory('messaging', 'Messaging', ERROR_MAP);
3708
3709    /**
3710     * @license
3711     * Copyright 2019 Google LLC
3712     *
3713     * Licensed under the Apache License, Version 2.0 (the "License");
3714     * you may not use this file except in compliance with the License.
3715     * You may obtain a copy of the License at
3716     *
3717     *   http://www.apache.org/licenses/LICENSE-2.0
3718     *
3719     * Unless required by applicable law or agreed to in writing, software
3720     * distributed under the License is distributed on an "AS IS" BASIS,
3721     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
3722     * See the License for the specific language governing permissions and
3723     * limitations under the License.
3724     */
3725    const DATABASE_NAME = 'firebase-messaging-database';
3726    const DATABASE_VERSION = 2;
3727    const TOKEN_OBJECT_STORE_NAME = 'firebase-messaging-store';
3728    const FID_REGISTRATION_OBJECT_STORE_NAME = 'firebase-messaging-fid-registration-store';
3729    const defaultIdb = { openDB, deleteDB };
3730    let idbImpl = defaultIdb;
3731    // Open v2, but fall back to v1 if upgrade/open fails. Cache as `unknown` and guard store access.
3732    let dbPromise = null;
3733    function migrateMessagingDb(upgradeDb, oldVersion, targetSchemaVersion) {
3734        // Intentional fall-through for v2: run all intermediate migrations.
3735        // eslint-disable-next-line default-case
3736        switch (oldVersion) {
3737            case 0:
3738                upgradeDb.createObjectStore(TOKEN_OBJECT_STORE_NAME);
3739                if (targetSchemaVersion === 1) {
3740                    break;
3741                }
3742            // fall through
3743            case 1:
3744                if (targetSchemaVersion === 2) {
3745                    upgradeDb.createObjectStore(FID_REGISTRATION_OBJECT_STORE_NAME);
3746                }
3747        }
3748    }
3749    function createOpenDbOptions(targetSchemaVersion) {
3750        return {
3751            upgrade: (upgradeDb, oldVersion) => {
3752                migrateMessagingDb(upgradeDb, oldVersion, targetSchemaVersion);
3753            },
3754            blocked: () => {
3755                /* no-op */
3756            },
3757            blocking: (_currentVersion, _blockedVersion, event) => {
3758                dbPromise = null;
3759                event.target?.close();
3760            },
3761            terminated: () => {
3762                dbPromise = null;
3763            }
3764        };
3765    }
3766    function getDbPromise() {
3767        if (!dbPromise) {
3768            const openLatest = idbImpl.openDB(DATABASE_NAME, DATABASE_VERSION, createOpenDbOptions(2));
3769            // Assign synchronously to avoid concurrent openDB() calls.
3770            dbPromise = openLatest.catch(() => idbImpl.openDB(DATABASE_NAME, DATABASE_VERSION - 1, createOpenDbOptions(1)));
3771        }
3772        return dbPromise;
3773    }
3774    function hasObjectStore(db, storeName) {
3775        return db.objectStoreNames.contains(storeName);
3776    }
3777    function assertFidRegistrationObjectStore(db) {
3778        if (!hasObjectStore(db, FID_REGISTRATION_OBJECT_STORE_NAME)) {
3779            throw ERROR_FACTORY.create("fid-registration-idb-schema-unavailable" /* ErrorCode.FID_REGISTRATION_IDB_SCHEMA_UNAVAILABLE */);
3780        }
3781    }
3782    async function dbGet(firebaseDependencies) {
3783        const key = getKey(firebaseDependencies);
3784        const db = await getDbPromise();
3785        const tokenDetails = (await db
3786            .transaction(TOKEN_OBJECT_STORE_NAME)
3787            .objectStore(TOKEN_OBJECT_STORE_NAME)
3788            .get(key));
3789        if (tokenDetails) {
3790            return tokenDetails;
3791        }
3792        else {
3793            const oldTokenDetails = await migrateOldDatabase(firebaseDependencies.appConfig.senderId);
3794            if (oldTokenDetails) {
3795                await dbSet(firebaseDependencies, oldTokenDetails);
3796                return oldTokenDetails;
3797            }
3798        }
3799    }
3800    async function dbSet(firebaseDependencies, tokenDetails) {
3801        const key = getKey(firebaseDependencies);
3802        const db = await getDbPromise();
3803        const stores = [TOKEN_OBJECT_STORE_NAME];
3804        const hasFidStore = hasObjectStore(db, FID_REGISTRATION_OBJECT_STORE_NAME);
3805        if (hasFidStore) {
3806            stores.push(FID_REGISTRATION_OBJECT_STORE_NAME);
3807        }
3808        const tx = db.transaction(stores, 'readwrite');
3809        await tx.objectStore(TOKEN_OBJECT_STORE_NAME).put(tokenDetails, key);
3810        if (hasFidStore) {
3811            await tx.objectStore(FID_REGISTRATION_OBJECT_STORE_NAME).delete(key);
3812        }
3813        await tx.done;
3814        return tokenDetails;
3815    }
3816    async function dbRemove(firebaseDependencies) {
3817        const key = getKey(firebaseDependencies);
3818        const db = await getDbPromise();
3819        const tx = db.transaction(TOKEN_OBJECT_STORE_NAME, 'readwrite');
3820        await tx.objectStore(TOKEN_OBJECT_STORE_NAME).delete(key);
3821        await tx.done;
3822    }
3823    async function dbGetFidRegistration(firebaseDependencies) {
3824        const key = getKey(firebaseDependencies);
3825        const db = await getDbPromise();
3826        assertFidRegistrationObjectStore(db);
3827        return (await db
3828            .transaction(FID_REGISTRATION_OBJECT_STORE_NAME)
3829            .objectStore(FID_REGISTRATION_OBJECT_STORE_NAME)
3830            .get(key));
3831    }
3832    async function dbSetFidRegistration(firebaseDependencies, details) {
3833        const key = getKey(firebaseDependencies);
3834        const db = await getDbPromise();
3835        assertFidRegistrationObjectStore(db);
3836        const tx = db.transaction([TOKEN_OBJECT_STORE_NAME, FID_REGISTRATION_OBJECT_STORE_NAME], 'readwrite');
3837        await tx.objectStore(FID_REGISTRATION_OBJECT_STORE_NAME).put(details, key);
3838        await tx.objectStore(TOKEN_OBJECT_STORE_NAME).delete(key);
3839        await tx.done;
3840        return details;
3841    }
3842    async function dbRemoveFidRegistration(firebaseDependencies) {
3843        const key = getKey(firebaseDependencies);
3844        const db = await getDbPromise();
3845        assertFidRegistrationObjectStore(db);
3846        const tx = db.transaction(FID_REGISTRATION_OBJECT_STORE_NAME, 'readwrite');
3847        await tx.objectStore(FID_REGISTRATION_OBJECT_STORE_NAME).delete(key);
3848        await tx.done;
3849    }
3850    function getKey({ appConfig }) {
3851        return appConfig.appId;
3852    }
3853
3854    const version = "0.13.0";
3855
3856    /**
3857     * @license
3858     * Copyright 2019 Google LLC
3859     *
3860     * Licensed under the Apache License, Version 2.0 (the "License");
3861     * you may not use this file except in compliance with the License.
3862     * You may obtain a copy of the License at
3863     *
3864     *   http://www.apache.org/licenses/LICENSE-2.0
3865     *
3866     * Unless required by applicable law or agreed to in writing, software
3867     * distributed under the License is distributed on an "AS IS" BASIS,
3868     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
3869     * See the License for the specific language governing permissions and
3870     * limitations under the License.
3871     */
3872    /** Max attempts (initial fetch + retries) when CreateRegistration `fetch()` throws. */
3873    const FID_REGISTRATION_FETCH_MAX_ATTEMPTS = 3;
3874    /** Base delay in ms; backoff is `BASE * 2^attempt` after each failed attempt. */
3875    const FID_REGISTRATION_FETCH_BASE_BACKOFF_MS = 1000;
3876    async function requestGetToken(firebaseDependencies, subscriptionOptions) {
3877        const headers = await getHeaders(firebaseDependencies);
3878        const body = getBody(subscriptionOptions, firebaseDependencies.appConfig.appName, 
3879        /* includeSdkVersion= */ false);
3880        const subscribeOptions = {
3881            method: 'POST',
3882            headers,
3883            body: JSON.stringify(body)
3884        };
3885        let responseData;
3886        try {
3887            const response = await fetch(getEndpoint(firebaseDependencies.appConfig), subscribeOptions);
3888            responseData = await response.json();
3889        }
3890        catch (err) {
3891            throw ERROR_FACTORY.create("token-subscribe-failed" /* ErrorCode.TOKEN_SUBSCRIBE_FAILED */, {
3892                errorInfo: err?.toString()
3893            });
3894        }
3895        if (responseData.error) {
3896            const message = responseData.error.message;
3897            throw ERROR_FACTORY.create("token-subscribe-failed" /* ErrorCode.TOKEN_SUBSCRIBE_FAILED */, {
3898                errorInfo: message
3899            });
3900        }
3901        if (!responseData.token) {
3902            throw ERROR_FACTORY.create("token-subscribe-no-token" /* ErrorCode.TOKEN_SUBSCRIBE_NO_TOKEN */);
3903        }
3904        return responseData.token;
3905    }
3906    async function requestCreateRegistration(firebaseDependencies, subscriptionOptions) {
3907        const headers = await getHeaders(firebaseDependencies);
3908        const body = getBody(subscriptionOptions, firebaseDependencies.appConfig.appName, 
3909        /* includeSdkVersion= */ true);
3910        const subscribeOptions = {
3911            method: 'POST',
3912            headers,
3913            body: JSON.stringify(body)
3914        };
3915        let response;
3916        try {
3917            response = await fetchWithExponentialRetry(() => fetch(getEndpoint(firebaseDependencies.appConfig), subscribeOptions), FID_REGISTRATION_FETCH_MAX_ATTEMPTS, FID_REGISTRATION_FETCH_BASE_BACKOFF_MS);
3918        }
3919        catch (err) {
3920            throw ERROR_FACTORY.create("fid-registration-failed" /* ErrorCode.FID_REGISTRATION_FAILED */, {
3921                errorInfo: err?.toString()
3922            });
3923        }
3924        if (response.ok) {
3925            const responseFid = await parseCreateRegistrationSuccessFid(response);
3926            return { responseFid };
3927        }
3928        // `fetch()` succeeded, but the backend returned a non-2xx response.
3929        // Best-effort parse the body to extract `error.message`, but always fail with
3930        // `FID_REGISTRATION_FAILED` to keep the error surface uniform.
3931        // Best-effort extraction of error details; the main signal is response.ok / status.
3932        let responseData;
3933        try {
3934            responseData = (await response.json());
3935        }
3936        catch (err) {
3937            throw ERROR_FACTORY.create("fid-registration-failed" /* ErrorCode.FID_REGISTRATION_FAILED */, {
3938                errorInfo: response.statusText
3939            });
3940        }
3941        const message = responseData.error?.message ?? response.statusText;
3942        throw ERROR_FACTORY.create("fid-registration-failed" /* ErrorCode.FID_REGISTRATION_FAILED */, {
3943            errorInfo: message
3944        });
3945    }
3946    /**
3947     * Deletes an FCM Web registration via DeleteRegistration using the Firebase Installation ID (FID).
3948     */
3949    async function requestDeleteRegistration(firebaseDependencies, fid) {
3950        const headers = await getHeaders(firebaseDependencies);
3951        const options = {
3952            method: 'DELETE',
3953            headers
3954        };
3955        let response;
3956        try {
3957            response = await fetch(`${getEndpoint(firebaseDependencies.appConfig)}
3957/${fid}`, options);
3958        }
3959        catch (err) {
3960            throw ERROR_FACTORY.create("fid-unregister-failed" /* ErrorCode.FID_UNREGISTER_FAILED */, {
3961                errorInfo: err?.toString()
3962            });
3963        }
3964        if (response.ok) {
3965            return;
3966        }
3967        // Best-effort parse error details; surface uniform error code.
3968        try {
3969            const responseData = (await response.json());
3970            const message = responseData.error?.message ?? response.statusText;
3971            throw message;
3972        }
3973        catch (err) {
3974            // If parsing failed, fall back to status text.
3975            throw ERROR_FACTORY.create("fid-unregister-failed" /* ErrorCode.FID_UNREGISTER_FAILED */, {
3976                errorInfo: (typeof err === 'string' && err) ||
3977                    response.statusText ||
3978                    err?.toString()
3979            });
3980        }
3981    }
3982    /**
3983     * Parses a successful CreateRegistration body. The backend must return JSON with a non-empty
3984     * string `name`: a resource name `projects/{projectId}/registrations/{fid}`
3985     */
3986    async function parseCreateRegistrationSuccessFid(response) {
3987        const text = await response.text();
3988        if (!text.trim()) {
3989            throw ERROR_FACTORY.create("fid-registration-failed" /* ErrorCode.FID_REGISTRATION_FAILED */, {
3990                errorInfo: 'CreateRegistration succeeded but response body is empty'
3991            });
3992        }
3993        let data;
3994        try {
3995            data = JSON.parse(text);
3996        }
3997        catch {
3998            throw ERROR_FACTORY.create("fid-registration-failed" /* ErrorCode.FID_REGISTRATION_FAILED */, {
3999                errorInfo: 'CreateRegistration succeeded but response body is not valid JSON'
4000            });
4001        }
4002        const name = data.name;
4003        if (typeof name !== 'string' || name.length === 0) {
4004            throw ERROR_FACTORY.create("fid-registration-failed" /* ErrorCode.FID_REGISTRATION_FAILED */, {
4005                errorInfo: 'CreateRegistration succeeded but response did not include a non-empty name'
4006            });
4007        }
4008        return parseFidFromRegistrationResourceName(name);
4009    }
4010    const REGISTRATIONS_NAME_SEGMENT = '/registrations/';
4011    /** Extracts the Firebase Installation ID from CreateRegistration `name` (resource path). */
4012    function parseFidFromRegistrationResourceName(name) {
4013        const segmentIndex = name.indexOf(REGISTRATIONS_NAME_SEGMENT);
4014        if (segmentIndex !== -1) {
4015            const fid = name.slice(segmentIndex + REGISTRATIONS_NAME_SEGMENT.length);
4016            if (fid.length > 0) {
4017                return fid;
4018            }
4019        }
4020        throw ERROR_FACTORY.create("fid-registration-failed" /* ErrorCode.FID_REGISTRATION_FAILED */, {
4021            errorInfo: 'CreateRegistration succeeded but response name is not a valid registration resource name'
4022        });
4023    }
4024    async function requestUpdateToken(firebaseDependencies, tokenDetails) {
4025        const headers = await getHeaders(firebaseDependencies);
4026        const body = getBody(tokenDetails.subscriptionOptions, firebaseDependencies.appConfig.appName, 
4027        /* includeSdkVersion= */ false);
4028        const updateOptions = {
4029            method: 'PATCH',
4030            headers,
4031            body: JSON.stringify(body)
4032        };
4033        let responseData;
4034        try {
4035            const response = await fetch(`${getEndpoint(firebaseDependencies.appConfig)}/${tokenDetails.token}`, updateOptions);
4036            responseData = await response.json();
4037        }
4038        catch (err) {
4039            throw ERROR_FACTORY.create("token-update-failed" /* ErrorCode.TOKEN_UPDATE_FAILED */, {
4040                errorInfo: err?.toString()
4041            });
4042        }
4043        if (responseData.error) {
4044            const message = responseData.error.message;
4045            throw ERROR_FACTORY.create("token-update-failed" /* ErrorCode.TOKEN_UPDATE_FAILED */, {
4046                errorInfo: message
4047            });
4048        }
4049        if (!responseData.token) {
4050            throw ERROR_FACTORY.create("token-update-no-token" /* ErrorCode.TOKEN_UPDATE_NO_TOKEN */);
4051        }
4052        return responseData.token;
4053    }
4054    async function requestDeleteToken(firebaseDependencies, token) {
4055        const headers = await getHeaders(firebaseDependencies);
4056        const unsubscribeOptions = {
4057            method: 'DELETE',
4058            headers
4059        };
4060        try {
4061            const response = await fetch(`${getEndpoint(firebaseDependencies.appConfig)}
4061/${token}`, unsubscribeOptions);
4062            const responseData = await response.json();
4063            if (responseData.error) {
4064                const message = responseData.error.message;
4065                throw ERROR_FACTORY.create("token-unsubscribe-failed" /* ErrorCode.TOKEN_UNSUBSCRIBE_FAILED */, {
4066                    errorInfo: message
4067                });
4068            }
4069        }
4070        catch (err) {
4071            throw ERROR_FACTORY.create("token-unsubscribe-failed" /* ErrorCode.TOKEN_UNSUBSCRIBE_FAILED */, {
4072                errorInfo: err?.toString()
4073            });
4074        }
4075    }
4076    /**
4077     * Re-runs `operation` when it throws, with exponential backoff between attempts.
4078     * Rethrows the last error if all attempts fail.
4079     */
4080    async function fetchWithExponentialRetry(operation, maxAttempts, baseBackoffMs) {
4081        let lastError;
4082        for (let attempt = 0; attempt < maxAttempts; attempt++) {
4083            try {
4084                return await operation();
4085            }
4086            catch (err) {
4087                lastError = err;
4088                if (attempt < maxAttempts - 1) {
4089                    const delayMs = baseBackoffMs * Math.pow(2, attempt);
4090                    await new Promise(resolve => setTimeout(resolve, delayMs));
4091                }
4092            }
4093        }
4094        throw lastError;
4095    }
4096    function getEndpoint({ projectId }) {
4097        return `${ENDPOINT}/projects/${projectId}/registrations`;
4098    }
4099    async function getHeaders({ appConfig, installations }) {
4100        const authToken = await installations.getToken();
4101        return new Headers({
4102            'Content-Type': 'application/json',
4103            Accept: 'application/json',
4104            'x-goog-api-key': appConfig.apiKey,
4105            'x-goog-firebase-installations-auth': `FIS ${authToken}`
4106        });
4107    }
4108    /**
4109     * Hostname for the registering web client (e.g. `www.example.com`), or the app name
4110     * (`appNameFallback`) when the scope cannot be resolved (e.g. some test environments).
4111     */
4112    function getRegistrationOrigin(swScope, appNameFallback) {
4113        try {
4114            if (/^[a-zA-Z][a-zA-Z\d+\-.]*:/.test(swScope)) {
4115                return new URL(swScope).host;
4116            }
4117        }
4118        catch {
4119            // Fall through to relative-scope handling.
4120        }
4121        try {
4122            if (typeof self !== 'undefined' && self.location?.href) {
4123                return new URL(swScope, self.location.origin).host;
4124            }
4125        }
4126        catch {
4127            // Fall through.
4128        }
4129        if (typeof self !== 'undefined' && self.location?.host) {
4130            return self.location.host;
4131        }
4132        return appNameFallback;
4133    }
4134    function getBody({ p256dh, auth, endpoint, vapidKey, swScope }, appNameFallback, includeSdkVersion) {
4135        const body = {
4136            web: {
4137                origin: getRegistrationOrigin(swScope, appNameFallback),
4138                endpoint,
4139                auth,
4140                p256dh
4141            }
4142        };
4143        if (includeSdkVersion) {
4144            // eslint-disable-next-line camelcase
4145            body.fcm_sdk_version = version;
4146        }
4147        if (vapidKey !== DEFAULT_VAPID_KEY) {
4148            body.web.applicationPubKey = vapidKey;
4149        }
4150        return body;
4151    }
4152
4153    /**
4154     * @license
4155     * Copyright 2019 Google LLC
4156     *
4157     * Licensed under the Apache License, Version 2.0 (the "License");
4158     * you may not use this file except in compliance with the License.
4159     * You may obtain a copy of the License at
4160     *
4161     *   http://www.apache.org/licenses/LICENSE-2.0
4162     *
4163     * Unless required by applicable law or agreed to in writing, software
4164     * distributed under the License is distributed on an "AS IS" BASIS,
4165     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
4166     * See the License for the specific language governing permissions and
4167     * limitations under the License.
4168     */
4169    // UpdateRegistration will be called once every week.
4170    const TOKEN_EXPIRATION_MS = 7 * 24 * 60 * 60 * 1000; // 7 days
4171    async function getTokenInternal(messaging) {
4172        const pushSubscription = await getPushSubscription$1(messaging.swRegistration, messaging.vapidKey);
4173        const subscriptionOptions = {
4174            vapidKey: messaging.vapidKey,
4175            swScope: messaging.swRegistration.scope,
4176            endpoint: pushSubscription.endpoint,
4177            auth: arrayToBase64(pushSubscription.getKey('auth')),
4178            p256dh: arrayToBase64(pushSubscription.getKey('p256dh'))
4179        };
4180        const tokenDetails = await dbGet(messaging.firebaseDependencies);
4181        if (!tokenDetails) {
4182            // No token, get a new one.
4183            return getNewToken(messaging.firebaseDependencies, subscriptionOptions);
4184        }
4185        else if (!isTokenValid(tokenDetails.subscriptionOptions, subscriptionOptions)) {
4186            // Invalid token, get a new one.
4187            try {
4188                await requestDeleteToken(messaging.firebaseDependencies, tokenDetails.token);
4189            }
4190            catch (e) {
4191                // Suppress errors because of #2364
4192                console.warn(e);
4193            }
4194            return getNewToken(messaging.firebaseDependencies, subscriptionOptions);
4195        }
4196        else if (Date.now() >= tokenDetails.createTime + TOKEN_EXPIRATION_MS) {
4197            // Weekly token refresh
4198            return updateToken(messaging, {
4199                token: tokenDetails.token,
4200                createTime: Date.now(),
4201                subscriptionOptions
4202            });
4203        }
4204        else {
4205            // Valid token, nothing to do.
4206            return tokenDetails.token;
4207        }
4208    }
4209    /**
4210     * Legacy getToken() path: there is a token row in IndexedDB. Revoke it with FCM, drop the row, and
4211     * clear any leftover FID registration metadata (apps may mix APIs).
4212     */
4213    async function revokeLegacyFcmTokenAndClearCaches(messaging, tokenDetails) {
4214        await requestDeleteToken(messaging.firebaseDependencies, tokenDetails.token);
4215        await dbRemove(messaging.firebaseDependencies);
4216        await removeFidRegistrationBestEffort(messaging.firebaseDependencies);
4217    }
4218    /**
4219     * No legacy token row: the client may only have FID-based registration (register() flow). If so,
4220     * delete that registration on the server, always scrub local FID metadata, then surface
4221     * onUnregistered when we actually had an FID.
4222     */
4223    async function revokeFidRegistrationIfStored(messaging) {
4224        const stored = await dbGetFidRegistration(messaging.firebaseDependencies).catch(() => undefined);
4225        const fid = stored?.fid;
4226        if (fid) {
4227            await requestDeleteRegistration(messaging.firebaseDependencies, fid);
4228        }
4229        await removeFidRegistrationBestEffort(messaging.firebaseDependencies);
4230        if (fid) {
4231            notifyOnUnregistered(messaging, fid);
4232        }
4233    }
4234    /**
4235     * Revokes the app's FCM registration: legacy token (getToken/deleteToken) and/or FI
vendor: 4,268 bytes, lines 4235-4349
4235D-based
4236     * registration (register/unregister), clears local caches, notifies onUnregistered when a stored
4237     * FID existed, then unsubscribes the push subscription when present.
4238     */
4239    async function revokeRegistrationInternal(messaging) {
4240        const tokenDetails = await dbGet(messaging.firebaseDependencies);
4241        if (tokenDetails) {
4242            await revokeLegacyFcmTokenAndClearCaches(messaging, tokenDetails);
4243        }
4244        else {
4245            await revokeFidRegistrationIfStored(messaging);
4246        }
4247        // Unsubscribe from the push subscription.
4248        const pushSubscription = await messaging.swRegistration.pushManager.getSubscription();
4249        if (pushSubscription) {
4250            return pushSubscription.unsubscribe();
4251        }
4252        // If there's no SW, consider it a success.
4253        return true;
4254    }
4255    async function updateToken(messaging, tokenDetails) {
4256        try {
4257            const updatedToken = await requestUpdateToken(messaging.firebaseDependencies, tokenDetails);
4258            const updatedTokenDetails = {
4259                ...tokenDetails,
4260                token: updatedToken,
4261                createTime: Date.now()
4262            };
4263            await dbSet(messaging.firebaseDependencies, updatedTokenDetails);
4264            return updatedToken;
4265        }
4266        catch (e) {
4267            throw e;
4268        }
4269    }
4270    async function getNewToken(firebaseDependencies, subscriptionOptions) {
4271        const token = await requestGetToken(firebaseDependencies, subscriptionOptions);
4272        const tokenDetails = {
4273            token,
4274            createTime: Date.now(),
4275            subscriptionOptions
4276        };
4277        await dbSet(firebaseDependencies, tokenDetails);
4278        return tokenDetails.token;
4279    }
4280    /**
4281     * Gets a PushSubscription for the current user.
4282     */
4283    async function getPushSubscription$1(swRegistration, vapidKey) {
4284        const subscription = await swRegistration.pushManager.getSubscription();
4285        if (subscription) {
4286            return subscription;
4287        }
4288        return swRegistration.pushManager.subscribe({
4289            userVisibleOnly: true,
4290            // Chrome <= 75 doesn't support base64-encoded VAPID key. For backward compatibility, VAPID key
4291            // submitted to pushManager#subscribe must be of type Uint8Array.
4292            applicationServerKey: base64ToArray(vapidKey)
4293        });
4294    }
4295    /**
4296     * Checks if the saved tokenDetails object matches the configuration provided.
4297     */
4298    function isTokenValid(dbOptions, currentOptions) {
4299        const isVapidKeyEqual = currentOptions.vapidKey === dbOptions.vapidKey;
4300        const isEndpointEqual = currentOptions.endpoint === dbOptions.endpoint;
4301        const isAuthEqual = currentOptions.auth === dbOptions.auth;
4302        const isP256dhEqual = currentOptions.p256dh === dbOptions.p256dh;
4303        return isVapidKeyEqual && isEndpointEqual && isAuthEqual && isP256dhEqual;
4304    }
4305    /** Clears FID registration metadata; apps may mix legacy getToken() with FID register/unregister. */
4306    async function removeFidRegistrationBestEffort(firebaseDependencies) {
4307        try {
4308            await dbRemoveFidRegistration(firebaseDependencies);
4309        }
4310        catch {
4311            // Ignore.
4312        }
4313    }
4314    function notifyOnRegistered(messaging, fid) {
4315        const handler = messaging.onRegisteredHandler;
4316        if (!handler) {
4317            return;
4318        }
4319        if (typeof handler === 'function') {
4320            handler(fid);
4321        }
4322        else {
4323            handler.next(fid);
4324        }
4325    }
4326    function notifyOnUnregistered(messaging, fid) {
4327        const handler = messaging.onUnregisteredHandler;
4328        if (!handler) {
4329            return;
4330        }
4331        if (typeof handler === 'function') {
4332            handler(fid);
4333        }
4334        else {
4335            handler.next(fid);
4336        }
4337    }
4338
4339    /**
4340     * @license
4341     * Copyright 2020 Google LLC
4342     *
4343     * Licensed under the Apache License, Version 2.0 (the "License");
4344     * you may not use this file except in compliance with the License.
4345     * You may obtain a copy of the License at
4346     *
4347     *   http://www.apache.org/licenses/LICENSE-2.0
4348     *
4349     * Unless required by applicable law or agreed to in writing, softw
4349are
4350     * distributed under the License is distributed on an "AS IS" BASIS,
4351     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
4352     * See the License for the specific language governing permissions and
4353     * limitations under the License.
4354     */
4355    async function updateVapidKey(messaging, vapidKey) {
4356        if (!!vapidKey) {
4357            messaging.vapidKey = vapidKey;
4358        }
4359        else if (!messaging.vapidKey) {
4360            messaging.vapidKey = DEFAULT_VAPID_KEY;
4361        }
4362    }
4363
4364    /**
4365     * @license
4366     * Copyright 2020 Google LLC
4367     *
4368     * Licensed under the Apache License, Version 2.0 (the "License");
4369     * you may not use this file except in compliance with the License.
4370     * You may obtain a copy of the License at
4371     *
4372     *   http://www.apache.org/licenses/LICENSE-2.0
4373     *
4374     * Unless required by applicable law or agreed to in writing, software
4375     * distributed under the License is distributed on an "AS IS" BASIS,
4376     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
4377     * See the License for the specific language governing permissions and
4378     * limitations under the License.
4379     */
4380    /** Retries when CreateRegistration echoes an FID that does not match Installations.getId(). */
4381    const FID_REGISTRATION_FID_MATCH_MAX_ATTEMPTS = 3;
4382    /**
4383     * For the new FID-based register path:
4384     * - Create (or refresh) an FCM Web registration in the backend via CreateRegistration.
4385     * - Use the FIS auth token produced by the installations instance (implicitly associated with FID).
4386     * - CreateRegistration must echo the installation in `name` (e.g.
4387     *   `projects/{projectId}/registrations/{fid}`); it must match `expectedFid` from
4388     *   Installations.getId(). On mismatch we refresh the auth token and retry, then fail with
4389     *   `fid-registration-failed`.
4390     */
4391    async function registerFcmRegistrationWithFid(messaging, expectedFid) {
4392        const pushSubscription = await getPushSubscription(messaging.swRegistration, messaging.vapidKey);
4393        const subscriptionOptions = {
4394            vapidKey: messaging.vapidKey,
4395            swScope: messaging.swRegistration.scope,
4396            endpoint: pushSubscription.endpoint,
4397            auth: arrayToBase64(pushSubscription.getKey('auth')),
4398            p256dh: arrayToBase64(pushSubscription.getKey('p256dh'))
4399        };
4400        const installations = messaging.firebaseDependencies.installations;
4401        for (let attempt = 0; attempt < FID_REGISTRATION_FID_MATCH_MAX_ATTEMPTS; attempt++) {
4402            const { responseFid } = await requestCreateRegistration(messaging.firebaseDependencies, subscriptionOptions);
4403            if (responseFid === expectedFid) {
4404                return;
4405            }
4406            // If CreateRegistration echoes an unexpected FID, the FIS auth token used for the request may
4407            // be stale relative to the installation the backend associates with the call. Force-refresh
4408            // the token before retrying so the next attempt uses credentials aligned with Installations.
4409            if (attempt < FID_REGISTRATION_FID_MATCH_MAX_ATTEMPTS - 1) {
4410                await installations.getToken(true);
4411            }
4412        }
4413        throw ERROR_FACTORY.create("fid-registration-failed" /* ErrorCode.FID_REGISTRATION_FAILED */, {
4414            errorInfo: 'CreateRegistration response FID does not match Firebase Installation ID'
4415        });
4416    }
4417    async function getPushSubscription(swRegistration, vapidKey) {
4418        const subscription = await swRegistration.pushManager.getSubscription();
4419        if (subscription) {
4420            return subscription;
4421        }
4422        // Chrome/Firefox require applicationServerKey to be of type Uint8Array.
4423        return swRegistration.pushManager.subscribe({
4424            userVisibleOnly: true,
4425            // `PushManager.subscribe` expects a `BufferSource`; `base64ToArray` produces a typed array.
4426            // Cast to satisfy the lib typing differences across TS DOM versions.
4427            applicationServerKey: base64ToArray(vapidKey)
4428        });
4429    }
4430
4431    /**
4432     * @license
4433     * Copyright 2026 Google LLC
4434     *
4435     * Licensed under the Apache License, Version 2.0 (the "License");
4436     * you may not use this file except in compliance with the License.
4437     * You may obtain a copy of the License at
4438     *
4439     *   http://www.apache.org/licenses/LICENSE-2.0
4440     *
4441     * Unless required by applicable law or agreed to in writing, software
4442     * distributed under the License is distributed on an "AS IS" BASIS,
4443     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
4444     * See the License for the specific language governing permissions and
4445     * limitations under the License.
4446     */
4447    /**
4448     * Re-runs FCM FID registration when push subscription keys change (e.g. `pushsubscriptionchange`
4449     * in the service worker). No-op if the app instance was never registered via `register()`.
4450     * Best-effort: callers should catch failures when permission or push may be unavailable.
4451     */
4452    async function refreshFidRegistrationIfStored(messaging) {
4453        const stored = await dbGetFidRegistration(messaging.firebaseDependencies).catch(() => undefined);
4454        if (!stored) {
4455            return undefined;
4456        }
4457        await updateVapidKey(messaging, stored.vapidKey);
4458        const fid = await messaging.firebaseDependencies.installations.getId();
4459        await registerFcmRegistrationWithFid(messaging, fid);
4460        await dbSetFidRegistration(messaging.firebaseDependencies, {
4461            fid,
4462            lastRegisterTime: Date.now(),
4463            vapidKey: messaging.vapidKey
4464        });
4465        notifyOnRegistered(messaging, fid);
4466        return fid;
4467    }
4468
4469    /**
4470     * @license
4471     * Copyright 2020 Google LLC
4472     *
4473     * Licensed under the Apache License, Version 2.0 (the "License");
4474     * you may not use this file except in compliance with the License.
4475     * You may obtain a copy of the License at
4476     *
4477     *   http://www.apache.org/licenses/LICENSE-2.0
4478     *
4479     * Unless required by applicable law or agreed to in writing, software
4480     * distributed under the License is distributed on an "AS IS" BASIS,
4481     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
4482     * See the License for the specific language governing permissions and
4483     * limitations under the License.
4484     */
4485    function externalizePayload(internalPayload) {
4486        const payload = {
4487            from: internalPayload.from,
4488            // eslint-disable-next-line camelcase
4489            collapseKey: internalPayload.collapse_key,
4490            // eslint-disable-next-line camelcase
4491            messageId: internalPayload.fcmMessageId
4492        };
4493        propagateNotificationPayload(payload, internalPayload);
4494        propagateDataPayload(payload, internalPayload);
4495        propagateFcmOptions(payload, internalPayload);
4496        return payload;
4497    }
4498    function propagateNotificationPayload(payload, messagePayloadInternal) {
4499        if (!messagePayloadInternal.notification) {
4500            return;
4501        }
4502        payload.notification = {};
4503        const title = messagePayloadInternal.notification.title;
4504        if (!!title) {
4505            payload.notification.title = title;
4506        }
4507        const body = messagePayloadInternal.notification.body;
4508        if (!!body) {
4509            payload.notification.body = body;
4510        }
4511        const image = messagePayloadInternal.notification.image;
4512        if (!!image) {
4513            payload.notification.image = image;
4514        }
4515        const icon = messagePayloadInternal.notification.icon;
4516        if (!!icon) {
4517            payload.notification.icon = icon;
4518        }
4519    }
4520    function propagateDataPayload(payload, messagePayloadInternal) {
4521        if (!messagePayloadInternal.data) {
4522            return;
4523        }
4524        payload.data = messagePayloadInternal.data;
4525    }
4526    function propagateFcmOptions(payload, messagePayloadInternal) {
4527        // fcmOptions.link value is written into notification.click_action. see more in b/232072111
4528        if (!messagePayloadInternal.fcmOptions &&
4529            !messagePayloadInternal.notification?.click_action) {
4530            return;
4531        }
4532        payload.fcmOptions = {};
4533        const link = messagePayloadInternal.fcmOptions?.link ??
4534            messagePayloadInternal.notification?.click_action;
4535        if (!!link) {
4536            payload.fcmOptions.link = link;
4537        }
4538        // eslint-disable-next-line camelcase
4539        const analyticsLabel = messagePayloadInternal.fcmOptions?.analytics_label;
4540        if (!!analyticsLabel) {
4541            payload.fcmOptions.analyticsLabel = analyticsLabel;
4542        }
4543    }
4544
4545    /**
4546     * @license
4547     * Copyright 2019 Google LLC
4548     *
4549     * Licensed under the Apache License, Version 2.0 (the "License");
vendor: 9,527 bytes, lines 4550-4776
4550     * you may not use this file except in compliance with the License.
4551     * You may obtain a copy of the License at
4552     *
4553     *   http://www.apache.org/licenses/LICENSE-2.0
4554     *
4555     * Unless required by applicable law or agreed to in writing, software
4556     * distributed under the License is distributed on an "AS IS" BASIS,
4557     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
4558     * See the License for the specific language governing permissions and
4559     * limitations under the License.
4560     */
4561    function isConsoleMessage(data) {
4562        // This message has a campaign ID, meaning it was sent using the Firebase Console.
4563        return typeof data === 'object' && !!data && CONSOLE_CAMPAIGN_ID in data;
4564    }
4565
4566    /**
4567     * @license
4568     * Copyright 2019 Google LLC
4569     *
4570     * Licensed under the Apache License, Version 2.0 (the "License");
4571     * you may not use this file except in compliance with the License.
4572     * You may obtain a copy of the License at
4573     *
4574     *   http://www.apache.org/licenses/LICENSE-2.0
4575     *
4576     * Unless required by applicable law or agreed to in writing, software
4577     * distributed under the License is distributed on an "AS IS" BASIS,
4578     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
4579     * See the License for the specific language governing permissions and
4580     * limitations under the License.
4581     */
4582    /** Returns a promise that resolves after given time passes. */
4583    function sleep(ms) {
4584        return new Promise(resolve => {
4585            setTimeout(resolve, ms);
4586        });
4587    }
4588
4589    /**
4590     * @license
4591     * Copyright 2019 Google LLC
4592     *
4593     * Licensed under the Apache License, Version 2.0 (the "License");
4594     * you may not use this file except in compliance with the License.
4595     * You may obtain a copy of the License at
4596     *
4597     *   http://www.apache.org/licenses/LICENSE-2.0
4598     *
4599     * Unless required by applicable law or agreed to in writing, software
4600     * distributed under the License is distributed on an "AS IS" BASIS,
4601     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
4602     * See the License for the specific language governing permissions and
4603     * limitations under the License.
4604     */
4605    const LOG_ENDPOINT = 'https://play.google.com/log?format=json_proto3';
4606    /** First flush ASAP (next timer turn); `_dispatchLogEvents` reschedules with `LOG_INTERVAL_IN_MS`. */
4607    const INITIAL_LOG_FLUSH_DELAY_MS = 0;
4608    const FCM_TRANSPORT_KEY = _mergeStrings('AzSCbw63g1R0nCw85jG8', 'Iaya3yLKwmgvh7cF0q4');
4609    function startLoggingService(messaging) {
4610        // Start only if not already scheduled/in-flight and there is work to do.
4611        if (messaging.logQueue.state === 'stopped' &&
4612            messaging.logEvents.length > 0) {
4613            _processQueue(messaging, INITIAL_LOG_FLUSH_DELAY_MS);
4614        }
4615    }
4616    /**
4617     *
4618     * @param messaging the messaging instance.
4619     * @param offsetInMs this method execute after `offsetInMs` elapsed .
4620     */
4621    function _processQueue(messaging, offsetInMs) {
4622        if (messaging.logQueue.state === 'scheduled') {
4623            clearTimeout(messaging.logQueue.timerId);
4624        }
4625        messaging.logQueue = { state: 'stopped' };
4626        if (!messaging.deliveryMetricsExportedToBigQueryEnabled) {
4627            messaging.logEvents = [];
4628            return;
4629        }
4630        messaging.logQueue = {
4631            state: 'scheduled',
4632            timerId: setTimeout(async () => {
4633                // Mark in-flight so stageLog/startLoggingService won't schedule duplicates mid-dispatch.
4634                messaging.logQueue = { state: 'flushing' };
4635                if (!messaging.logEvents.length) {
4636                    return _processQueue(messaging, LOG_INTERVAL_IN_MS);
4637                }
4638                await _dispatchLogEvents(messaging);
4639            }, offsetInMs)
4640        };
4641    }
4642    async function _dispatchLogEvents(messaging) {
4643        // Swap the queue to avoid losing events added during an in-flight dispatch.
4644        const eventsToSend = messaging.logEvents;
4645        messaging.logEvents = [];
4646        for (let i = 0, n = eventsToSend.length; i < n; i += MAX_NUMBER_OF_EVENTS_PER_LOG_REQUEST) {
4647            const batch = eventsToSend.slice(i, i + MAX_NUMBER_OF_EVENTS_PER_LOG_REQUEST);
4648            if (!batch.length) {
4649                break;
4650            }
4651            const logRequest = _createLogRequest(batch);
4652            let retryCount = 0, response = {};
4653            do {
4654                try {
4655                    response = await fetch(LOG_ENDPOINT.concat('&key=', FCM_TRANSPORT_KEY), {
4656                        method: 'POST',
4657                        body: JSON.stringify(logRequest)
4658                    });
4659                    // don't retry on 200s or non retriable errors
4660                    if (response.ok || (!response.ok && !isRetriableError(response))) {
4661                        break;
4662                    }
4663                    if (!response.ok && isRetriableError(response)) {
4664                        // rethrow to retry with quota
4665                        throw new Error('a retriable Non-200 code is returned in fetch to Firelog endpoint. Retry');
4666                    }
4667                }
4668                catch (error) {
4669                    const isLastAttempt = retryCount === MAX_RETRIES;
4670                    if (isLastAttempt) {
4671                        // existing the do-while interactive retry logic because retry quota has reached.
4672                        break;
4673                    }
4674                }
4675                let delayInMs;
4676                try {
4677                    delayInMs = Number((await response.json()).nextRequestWaitMillis);
4678                }
4679                catch (e) {
4680                    delayInMs = DEFAULT_BACKOFF_TIME_MS;
4681                }
4682                await new Promise(resolve => setTimeout(resolve, delayInMs));
4683                retryCount++;
4684            } while (retryCount < MAX_RETRIES);
4685        }
4686        // Schedule next flush. If new events arrived during this dispatch, flush ASAP.
4687        _processQueue(messaging, messaging.logEvents.length ? INITIAL_LOG_FLUSH_DELAY_MS : LOG_INTERVAL_IN_MS);
4688    }
4689    function isRetriableError(response) {
4690        const httpStatus = response.status;
4691        return (httpStatus === 429 ||
4692            httpStatus === 500 ||
4693            httpStatus === 503 ||
4694            httpStatus === 504);
4695    }
4696    async function stageLog(messaging, internalPayload) {
4697        const fcmEvent = createFcmEvent(internalPayload, await messaging.firebaseDependencies.installations.getId());
4698        createAndEnqueueLogEvent(messaging, fcmEvent, internalPayload.productId);
4699        startLoggingService(messaging);
4700    }
4701    function createFcmEvent(internalPayload, fid) {
4702        const fcmEvent = {};
4703        /* eslint-disable camelcase */
4704        // some fields should always be non-null. Still check to ensure.
4705        if (!!internalPayload.from) {
4706            fcmEvent.project_number = internalPayload.from;
4707        }
4708        if (!!internalPayload.fcmMessageId) {
4709            fcmEvent.message_id = internalPayload.fcmMessageId;
4710        }
4711        fcmEvent.instance_id = fid;
4712        if (!!internalPayload.notification) {
4713            fcmEvent.message_type = MessageType$1.DISPLAY_NOTIFICATION.toString();
4714        }
4715        else {
4716            fcmEvent.message_type = MessageType$1.DATA_MESSAGE.toString();
4717        }
4718        fcmEvent.sdk_platform = SDK_PLATFORM_WEB.toString();
4719        fcmEvent.package_name = self.origin.replace(/(^\w+:|^)\/\//, '');
4720        if (!!internalPayload.collapse_key) {
4721            fcmEvent.collapse_key = internalPayload.collapse_key;
4722        }
4723        fcmEvent.event = EVENT_MESSAGE_DELIVERED.toString();
4724        if (!!internalPayload.fcmOptions?.analytics_label) {
4725            fcmEvent.analytics_label = internalPayload.fcmOptions?.analytics_label;
4726        }
4727        /* eslint-enable camelcase */
4728        return fcmEvent;
4729    }
4730    function createAndEnqueueLogEvent(messaging, fcmEvent, productId) {
4731        const logEvent = {};
4732        /* eslint-disable camelcase */
4733        logEvent.event_time_ms = Math.floor(Date.now()).toString();
4734        logEvent.source_extension_json_proto3 = JSON.stringify({
4735            messaging_client_event: fcmEvent
4736        });
4737        if (!!productId) {
4738            logEvent.compliance_data = buildComplianceData(productId);
4739        }
4740        // eslint-disable-next-line camelcase
4741        messaging.logEvents.push(logEvent);
4742    }
4743    function buildComplianceData(productId) {
4744        const complianceData = {
4745            privacy_context: {
4746                prequest: {
4747                    origin_associated_product_id: productId
4748                }
4749            }
4750        };
4751        return complianceData;
4752    }
4753    function _createLogRequest(logEventQueue) {
4754        const logRequest = {};
4755        /* eslint-disable camelcase */
4756        logRequest.log_source = FCM_LOG_SOURCE.toString();
4757        logRequest.log_event = logEventQueue;
4758        /* eslint-enable camelcase */
4759        return logRequest;
4760    }
4761    function _mergeStrings(s1, s2) {
4762        const resultArray = [];
4763        for (let i = 0; i < s1.length; i++) {
4764            resultArray.push(s1.charAt(i));
4765            if (i < s2.length) {
4766                resultArray.push(s2.charAt(i));
4767            }
4768        }
4769        return resultArray.join('');
4770    }
4771
4772    /**
4773     * @license
4774     * Copyright 2017 Google LLC
4775     *
4776     * Licensed under the Apache License, Version 2.0 (the "License");
4777     * you may not use this file except in compliance with the License.
4778     * You may obtain a copy of the License at
4779     *
4780     *   http://www.apache.org/licenses/LICENSE-2.0
4781     *
4782     * Unless required by applicable law or agreed to in writing, software
4783     * distributed under the License is distributed on an "AS IS" BASIS,
4784     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
4785     * See the License for the specific language governing permissions and
4786     * limitations under the License.
4787     */
4788    async function onSubChange(event, messaging) {
4789        if (!messaging.swRegistration) {
4790            messaging.swRegistration = self.registration;
4791        }
4792        const { newSubscription } = event;
4793        if (!newSubscription) {
4794            // Subscription revoked: legacy token and FID register/unregister paths both flow through
4795            // revokeRegistrationInternal (server revoke + onUnregistered when applicable).
4796            await revokeRegistrationInternal(messaging);
4797            return;
4798        }
4799        const storedFid = await dbGetFidRegistration(messaging.firebaseDependencies).catch(() => undefined);
4800        if (storedFid) {
4801            const fid = await refreshFidRegistrationIfStored(messaging).catch(() => {
4802                // Best-effort: push subscription may be unavailable after rotation.
4803                return undefined;
4804            });
4805            if (fid) {
4806                const clientList = await getClientList();
4807                if (hasVisibleClients(clientList)) {
4808                    sendFidRegisteredToWindows(clientList, fid);
4809                }
4810            }
4811            return;
4812        }
4813        const tokenDetails = await dbGet(messaging.firebaseDependencies);
4814        await revokeRegistrationInternal(messaging);
4815        messaging.vapidKey =
4816            tokenDetails?.subscriptionOptions?.vapidKey ?? DEFAULT_VAPID_KEY;
4817        await getTokenInternal(messaging);
4818    }
4819    async function onPush(event, messaging) {
4820        const internalPayload = getMessagePayloadInternal(event);
4821        if (!internalPayload) {
4822            // Failed to get parsed MessagePayload from the PushEvent. Skip handling the push.
4823            return;
4824        }
4825        /*
4826         * Log to Firelog based on user consent. Rather than calling startLoggingService once when
4827         * deliveryMetricsExportedToBigQueryEnabled is toggled, we now call stageLog for every received push.
4828         * This ensures the first telemetry event is uploaded immediately upon enabling the flag, simplifying debugging.
4829         */
4830        if (messaging.deliveryMetricsExportedToBigQueryEnabled) {
4831            await stageLog(messaging, internalPayload);
4832        }
4833        // foreground handling: eventually passed to onMessage hook
4834        const clientList = await getClientList();
4835        if (hasVisibleClients(clientList)) {
4836            return sendMessagePayloadInternalToWindows(clientList, internalPayload);
4837        }
4838        // background handling: display if possible and pass to onBackgroundMessage hook
4839        if (!!internalPayload.notification) {
4840            await showNotification(wrapInternalPayload(internalPayload));
4841        }
4842        if (!messaging) {
4843            return;
4844        }
4845        if (!!messaging.onBackgroundMessageHandler) {
4846            const payload = externalizePayload(internalPayload);
4847            if (typeof messaging.onBackgroundMessageHandler === 'function') {
4848                await messaging.onBackgroundMessageHandler(payload);
4849            }
4850            else {
4851                messaging.onBackgroundMessageHandler.next(payload);
4852            }
4853        }
4854    }
4855    async function onNotificationClick(event) {
4856        const internalPayload = event.notification?.data?.[FCM_MSG];
4857        if (!internalPayload) {
4858            return;
4859        }
4860        else if (event.action) {
4861            // User clicked on an action button. This will allow developers to act on action button clicks
4862            // by using a custom onNotificationClick listener that they define.
4863            return;
4864        }
4865        // Prevent other listeners from receiving the event
4866        event.stopImmediatePropagation();
4867        event.notification.close();
4868        // Note clicking on a notification with no link set will focus the Chrome's current tab.
4869        const link = getLink(internalPayload);
4870        if (!link) {
4871            return;
4872        }
4873        // FM should only open/focus links from app's origin.
4874        const url = new URL(link, self.location.href);
4875        const originUrl = new URL(self.location.origin);
4876        if (url.host !== originUrl.host) {
4877            return;
4878        }
4879        let client = await getWindowClient(url);
4880        if (!client) {
4881            client = await self.clients.openWindow(link);
4882            // Wait three seconds for the client to initialize and set up the message handler so that it
4883            // can receive the message.
4884            await sleep(3000);
4885        }
4886        else {
4887            client = await client.focus();
4888        }
4889        if (!client) {
4890            // Window Client will not be returned if it's for a third party origin.
4891            return;
4892        }
4893        internalPayload.messageType = MessageType.NOTIFICATION_CLICKED;
4894        internalPayload.isFirebaseMessaging = true;
4895        return client.postMessage(internalPayload);
4896    }
4897    function wrapInternalPayload(internalPayload) {
4898        const wrappedInternalPayload = {
4899            ...internalPayload.notification
4900        };
4901        // Put the message payload under FCM_MSG name so we can identify the notification as being an FCM
4902        // notification vs a notification from somewhere else (i.e. normal web push or developer generated
4903        // notification).
4904        wrappedInternalPayload.data = {
4905            [FCM_MSG]: internalPayload
4906        };
4907        return wrappedInternalPayload;
4908    }
4909    function getMessagePayloadInternal({ data }) {
4910        if (!data) {
4911            return null;
4912        }
4913        try {
4914            return data.json();
4915        }
4916        catch (err) {
4917            // Not JSON so not an FCM message.
4918            return null;
4919        }
4920    }
4921    /**
vendor: 4,780 bytes, lines 4922-5049
4922     * @param url The URL to look for when focusing a client.
4923     * @return Returns an existing window client or a newly opened WindowClient.
4924     */
4925    async function getWindowClient(url) {
4926        const clientList = await getClientList();
4927        for (const client of clientList) {
4928            const clientUrl = new URL(client.url, self.location.href);
4929            if (url.host === clientUrl.host) {
4930                return client;
4931            }
4932        }
4933        return null;
4934    }
4935    /**
4936     * @returns If there is currently a visible WindowClient, this method will resolve to true,
4937     * otherwise false.
4938     */
4939    function hasVisibleClients(clientList) {
4940        return clientList.some(client => client.visibilityState === 'visible' &&
4941            // Ignore chrome-extension clients as that matches the background pages of extensions, which
4942            // are always considered visible for some reason.
4943            !client.url.startsWith('chrome-extension://'));
4944    }
4945    function sendMessagePayloadInternalToWindows(clientList, internalPayload) {
4946        internalPayload.isFirebaseMessaging = true;
4947        internalPayload.messageType = MessageType.PUSH_RECEIVED;
4948        for (const client of clientList) {
4949            client.postMessage(internalPayload);
4950        }
4951    }
4952    function sendFidRegisteredToWindows(clientList, fid) {
4953        const payload = {
4954            isFirebaseMessaging: true,
4955            messageType: MessageType.FID_REGISTERED,
4956            fid
4957        };
4958        for (const client of clientList) {
4959            client.postMessage(payload);
4960        }
4961    }
4962    function getClientList() {
4963        return self.clients.matchAll({
4964            type: 'window',
4965            includeUncontrolled: true
4966            // TS doesn't know that "type: 'window'" means it'll return WindowClient[]
4967        });
4968    }
4969    function showNotification(notificationPayloadInternal) {
4970        // Note: Firefox does not support the maxActions property.
4971        // https://developer.mozilla.org/en-US/docs/Web/API/notification/maxActions
4972        const { actions } = notificationPayloadInternal;
4973        const { maxActions } = Notification;
4974        if (actions && maxActions && actions.length > maxActions) {
4975            console.warn(`This browser only supports ${maxActions} actions. The remaining actions will not be displayed.`);
4976        }
4977        return self.registration.showNotification(
4978        /* title= */ notificationPayloadInternal.title ?? '', notificationPayloadInternal);
4979    }
4980    function getLink(payload) {
4981        // eslint-disable-next-line camelcase
4982        const link = payload.fcmOptions?.link ?? payload.notification?.click_action;
4983        if (link) {
4984            return link;
4985        }
4986        if (isConsoleMessage(payload.data)) {
4987            // Notification created in the Firebase Console. Redirect to origin.
4988            return self.location.origin;
4989        }
4990        else {
4991            return null;
4992        }
4993    }
4994
4995    /**
4996     * @license
4997     * Copyright 2019 Google LLC
4998     *
4999     * Licensed under the Apache License, Version 2.0 (the "License");
5000     * you may not use this file except in compliance with the License.
5001     * You may obtain a copy of the License at
5002     *
5003     *   http://www.apache.org/licenses/LICENSE-2.0
5004     *
5005     * Unless required by applicable law or agreed to in writing, software
5006     * distributed under the License is distributed on an "AS IS" BASIS,
5007     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
5008     * See the License for the specific language governing permissions and
5009     * limitations under the License.
5010     */
5011    function extractAppConfig(app) {
5012        if (!app || !app.options) {
5013            throw getMissingValueError('App Configuration Object');
5014        }
5015        if (!app.name) {
5016            throw getMissingValueError('App Name');
5017        }
5018        // Required app config keys
5019        const configKeys = [
5020            'projectId',
5021            'apiKey',
5022            'appId',
5023            'messagingSenderId'
5024        ];
5025        const { options } = app;
5026        for (const keyName of configKeys) {
5027            if (!options[keyName]) {
5028                throw getMissingValueError(keyName);
5029            }
5030        }
5031        return {
5032            appName: app.name,
5033            projectId: options.projectId,
5034            apiKey: options.apiKey,
5035            appId: options.appId,
5036            senderId: options.messagingSenderId
5037        };
5038    }
5039    function getMissingValueError(valueName) {
5040        return ERROR_FACTORY.create("missing-app-config-values" /* ErrorCode.MISSING_APP_CONFIG_VALUES */, {
5041            valueName
5042        });
5043    }
5044
5045    /**
5046     * @license
5047     * Copyright 2020 Google LLC
5048     *
5049     * Licensed under the Apache License, Version 2.0 (the "License");
5050     * you may not use this file except in compliance with the License.
5051     * You may obtain a copy of the License at
5052     *
5053     *   http://www.apache.org/licenses/LICENSE-2.0
5054     *
5055     * Unless required by applicable law or agreed to in writing, software
5056     * distributed under the License is distributed on an "AS IS" BASIS,
5057     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
5058     * See the License for the specific language governing permissions and
5059     * limitations under the License.
5060     */
5061    class MessagingService {
5062        constructor(app, installations, analyticsProvider) {
5063            // logging is only done with end user consent. Default to false.
5064            this.deliveryMetricsExportedToBigQueryEnabled = false;
5065            this.onBackgroundMessageHandler = null;
5066            this.onMessageHandler = null;
5067            /** Observer for the event that the app instance is registered with FCM via Firebase Installation ID (FID). */
5068            this.onRegisteredHandler = null;
5069            /** Observer for the event that the app instance is unregistered from FCM (FID no longer active). */
5070            this.onUnregisteredHandler = null;
5071            /**
5072             * Serializes the FID get + compare + notify step so concurrent register() calls
vendor: 4,334 bytes, lines 5073-5173
5073             * do not race each other.
5074             */
5075            this._registerNotifyChain = Promise.resolve();
5076            /** Unsubscribe from Installations `onIdChange` when messaging is deleted. */
5077            this._fidChangeUnsubscribe = null;
5078            this.logEvents = [];
5079            /**
5080             * Single source of truth for the logging loop lifecycle.
5081             *
5082             * `scheduled` holds the active timer id; `flushing` indicates an async dispatch
5083             * is in progress (prevents duplicate starts); `stopped` means idle.
5084             */
5085            this.logQueue = { state: 'stopped' };
5086            const appConfig = extractAppConfig(app);
5087            this.firebaseDependencies = {
5088                app,
5089                appConfig,
5090                installations,
5091                analyticsProvider
5092            };
5093        }
5094        _delete() {
5095            if (this._fidChangeUnsubscribe) {
5096                this._fidChangeUnsubscribe();
5097                this._fidChangeUnsubscribe = null;
5098            }
5099            if (this.logQueue.state === 'scheduled') {
5100                clearTimeout(this.logQueue.timerId);
5101            }
5102            this.logQueue = { state: 'stopped' };
5103            return Promise.resolve();
5104        }
5105    }
5106
5107    /**
5108     * @license
5109     * Copyright 2020 Google LLC
5110     *
5111     * Licensed under the Apache License, Version 2.0 (the "License");
5112     * you may not use this file except in compliance with the License.
5113     * You may obtain a copy of the License at
5114     *
5115     *   http://www.apache.org/licenses/LICENSE-2.0
5116     *
5117     * Unless required by applicable law or agreed to in writing, software
5118     * distributed under the License is distributed on an "AS IS" BASIS,
5119     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
5120     * See the License for the specific language governing permissions and
5121     * limitations under the License.
5122     */
5123    const SwMessagingFactory = (container) => {
5124        const messaging = new MessagingService(container.getProvider('app').getImmediate(), container.getProvider('installations-internal').getImmediate(), container.getProvider('analytics-internal'));
5125        self.addEventListener('push', e => {
5126            e.waitUntil(onPush(e, messaging));
5127        });
5128        self.addEventListener('pushsubscriptionchange', e => {
5129            e.waitUntil(onSubChange(e, messaging));
5130        });
5131        self.addEventListener('notificationclick', e => {
5132            e.waitUntil(onNotificationClick(e));
5133        });
5134        return messaging;
5135    };
5136    /**
5137     * The messaging instance registered in sw is named differently than that of in client. This is
5138     * because both `registerMessagingInWindow` and `registerMessagingInSw` would be called in
5139     * `messaging-compat` and component with the same name can only be registered once.
5140     */
5141    function registerMessagingInSw() {
5142        _registerComponent(new Component('messaging-sw', SwMessagingFactory, "PUBLIC" /* ComponentType.PUBLIC */));
5143    }
5144
5145    /**
5146     * @license
5147     * Copyright 2020 Google LLC
5148     *
5149     * Licensed under the Apache License, Version 2.0 (the "License");
5150     * you may not use this file except in compliance with the License.
5151     * You may obtain a copy of the License at
5152     *
5153     *   http://www.apache.org/licenses/LICENSE-2.0
5154     *
5155     * Unless required by applicable law or agreed to in writing, software
5156     * distributed under the License is distributed on an "AS IS" BASIS,
5157     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
5158     * See the License for the specific language governing permissions and
5159     * limitations under the License.
5160     */
5161    /**
5162     * Checks whether all required APIs exist within SW Context
5163     * @returns a Promise that resolves to a boolean.
5164     *
5165     * @public
5166     */
5167    async function isSwSupported() {
5168        // firebase-js-sdk/issues/2393 reveals that idb#open in Safari iframe and Firefox private browsing
5169        // might be prohibited to run. In these contexts, an error would be thrown during the messaging
5170        // instantiating phase, informing the developers to import/call isSupported for special handling.
5171        return (isIndexedDBAvailable() &&
5172            (await validateIndexedDBOpenable()) &&
5173            'PushManager' in self &&
5174            'Notification' in self &&
5175            ServiceWorkerRegistration.prototype.hasOwnProperty('showNotification') &&
5176            PushSubscription.prototype.hasOwnProperty('getKey'));
5177    }
5178
5179    /**
5180     * @license
5181     * Copyright 2017 Google LLC
5182     *
5183     * Licensed under the Apache License, Version 2.0 (the "License");
5184     * you may not use this file except in compliance with the License.
5185     * You may obtain a copy of the License at
5186     *
5187     *   http://www.apache.org/licenses/LICENSE-2.0
5188     *
5189     * Unless required by applicable law or agreed to in writing, software
5190     * distributed under the License is distributed on an "AS IS" BASIS,
5191     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
5192     * See the License for the specific language governing permissions and
5193     * limitations under the License.
5194     */
5195    /**
5196     * Retrieves a Firebase Cloud Messaging instance.
5197     *
5198     * @returns The Firebase Cloud Messaging instance associated with the provided firebase app.
5199     *
5200     * @public
5201     */
5202    function getMessagingInSw(app = getApp()) {
5203        // Conscious decision to make this async check non-blocking during the messaging instance
5204        // initialization phase for performance consideration. An error would be thrown latter for
5205        // developer's information. Developers can then choose to import and call `isSupported` for
5206        // special handling.
5207        isSwSupported().then(isSupported => {
5208            // If `isSwSupported()` resolved, but returned false.
5209            if (!isSupported) {
5210                throw ERROR_FACTORY.create("unsupported-browser" /* ErrorCode.UNSUPPORTED_BROWSER */);
5211            }
5212        }, _ => {
5213            // If `isSwSupported()` rejected.
5214            throw ERROR_FACTORY.create("indexed-db-unsupported" /* ErrorCode.INDEXED_DB_UNSUPPORTED */);
5215        });
5216        return _getProvider(getModularInstance(app), 'messaging-sw').getImmediate();
5217    }
5218
5219    /**
5220     * @license
5221     * Copyright 2017 Google LLC
5222     *
5223     * Licensed under the Apache License, Version 2.0 (the "License");
5224     * you may not use this file except in compliance with the License.
5225     * You may obtain a copy of the License at
5226     *
5227     *   http://www.apache.org/licenses/LICENSE-2.0
5228     *
5229     * Unless required by applicable law or agreed to in writing, software
5230     * distributed under the License is distributed on an "AS IS" BASIS,
5231     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
5232     * See the License for the specific language governing permissions and
5233     * limitations under the License.
5234     */
5235    registerMessagingInSw();
5236
5237    const firebaseConfig = {
5238        apiKey: 'AIzaSyBWJoz_wRUkFn32AF-YE6ZnFDy98AUXGcs',
5239        authDomain: 'daily-cat.firebaseapp.com',
5240        databaseURL: 'https://daily-cat.firebaseio.com',
5241        projectId: 'daily-cat',
5242        storageBucket: 'daily-cat.firebasestorage.app',
5243        messagingSenderId: '982124839218',
5244        appId: '1:982124839218:web:50c60b718f60eca718572b',
5245    };
5246
5247    /// <reference lib="webworker" />
5248    const app = initializeApp(firebaseConfig);
5249    getMessagingInSw(app);
5250
5251})();

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.