@thefittingroom/sdk 1.5.0 → 1.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/esm/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * thefittingroom v1.5.0 (2024-09-01T16:52:25.366Z)
2
+ * thefittingroom v1.5.2 (2024-09-03T15:43:56.403Z)
3
3
  * Copyright 2022-present, TheFittingRoom, Inc. All rights reserved.
4
4
  */
5
5
  // Code generated by tygo. DO NOT EDIT.
@@ -1947,8 +1947,8 @@ function isVersionServiceProvider(provider) {
1947
1947
  return (component === null || component === void 0 ? void 0 : component.type) === "VERSION" /* ComponentType.VERSION */;
1948
1948
  }
1949
1949
 
1950
- const name$o = "@firebase/app";
1951
- const version$1$1 = "0.9.13";
1950
+ const name$p = "@firebase/app";
1951
+ const version$1$1 = "0.10.9";
1952
1952
 
1953
1953
  /**
1954
1954
  * @license
@@ -1968,54 +1968,56 @@ const version$1$1 = "0.9.13";
1968
1968
  */
1969
1969
  const logger = new Logger$1('@firebase/app');
1970
1970
 
1971
- const name$n = "@firebase/app-compat";
1971
+ const name$o = "@firebase/app-compat";
1972
1972
 
1973
- const name$m = "@firebase/analytics-compat";
1973
+ const name$n = "@firebase/analytics-compat";
1974
1974
 
1975
- const name$l = "@firebase/analytics";
1975
+ const name$m = "@firebase/analytics";
1976
1976
 
1977
- const name$k = "@firebase/app-check-compat";
1977
+ const name$l = "@firebase/app-check-compat";
1978
1978
 
1979
- const name$j = "@firebase/app-check";
1979
+ const name$k = "@firebase/app-check";
1980
1980
 
1981
- const name$i = "@firebase/auth";
1981
+ const name$j = "@firebase/auth";
1982
1982
 
1983
- const name$h = "@firebase/auth-compat";
1983
+ const name$i = "@firebase/auth-compat";
1984
1984
 
1985
- const name$g = "@firebase/database";
1985
+ const name$h = "@firebase/database";
1986
1986
 
1987
- const name$f = "@firebase/database-compat";
1987
+ const name$g = "@firebase/database-compat";
1988
1988
 
1989
- const name$e = "@firebase/functions";
1989
+ const name$f = "@firebase/functions";
1990
1990
 
1991
- const name$d = "@firebase/functions-compat";
1991
+ const name$e = "@firebase/functions-compat";
1992
1992
 
1993
- const name$c = "@firebase/installations";
1993
+ const name$d = "@firebase/installations";
1994
1994
 
1995
- const name$b = "@firebase/installations-compat";
1995
+ const name$c = "@firebase/installations-compat";
1996
1996
 
1997
- const name$a = "@firebase/messaging";
1997
+ const name$b = "@firebase/messaging";
1998
1998
 
1999
- const name$9 = "@firebase/messaging-compat";
1999
+ const name$a = "@firebase/messaging-compat";
2000
2000
 
2001
- const name$8 = "@firebase/performance";
2001
+ const name$9 = "@firebase/performance";
2002
2002
 
2003
- const name$7 = "@firebase/performance-compat";
2003
+ const name$8 = "@firebase/performance-compat";
2004
2004
 
2005
- const name$6 = "@firebase/remote-config";
2005
+ const name$7 = "@firebase/remote-config";
2006
2006
 
2007
- const name$5 = "@firebase/remote-config-compat";
2007
+ const name$6 = "@firebase/remote-config-compat";
2008
2008
 
2009
- const name$4 = "@firebase/storage";
2009
+ const name$5 = "@firebase/storage";
2010
2010
 
2011
- const name$3 = "@firebase/storage-compat";
2011
+ const name$4 = "@firebase/storage-compat";
2012
2012
 
2013
- const name$2 = "@firebase/firestore";
2013
+ const name$3 = "@firebase/firestore";
2014
+
2015
+ const name$2 = "@firebase/vertexai-preview";
2014
2016
 
2015
2017
  const name$1$1 = "@firebase/firestore-compat";
2016
2018
 
2017
- const name$p = "firebase";
2018
- const version$2 = "9.23.0";
2019
+ const name$q = "firebase";
2020
+ const version$2 = "10.13.0";
2019
2021
 
2020
2022
  /**
2021
2023
  * @license
@@ -2040,32 +2042,33 @@ const version$2 = "9.23.0";
2040
2042
  */
2041
2043
  const DEFAULT_ENTRY_NAME = '[DEFAULT]';
2042
2044
  const PLATFORM_LOG_STRING = {
2043
- [name$o]: 'fire-core',
2044
- [name$n]: 'fire-core-compat',
2045
- [name$l]: 'fire-analytics',
2046
- [name$m]: 'fire-analytics-compat',
2047
- [name$j]: 'fire-app-check',
2048
- [name$k]: 'fire-app-check-compat',
2049
- [name$i]: 'fire-auth',
2050
- [name$h]: 'fire-auth-compat',
2051
- [name$g]: 'fire-rtdb',
2052
- [name$f]: 'fire-rtdb-compat',
2053
- [name$e]: 'fire-fn',
2054
- [name$d]: 'fire-fn-compat',
2055
- [name$c]: 'fire-iid',
2056
- [name$b]: 'fire-iid-compat',
2057
- [name$a]: 'fire-fcm',
2058
- [name$9]: 'fire-fcm-compat',
2059
- [name$8]: 'fire-perf',
2060
- [name$7]: 'fire-perf-compat',
2061
- [name$6]: 'fire-rc',
2062
- [name$5]: 'fire-rc-compat',
2063
- [name$4]: 'fire-gcs',
2064
- [name$3]: 'fire-gcs-compat',
2065
- [name$2]: 'fire-fst',
2045
+ [name$p]: 'fire-core',
2046
+ [name$o]: 'fire-core-compat',
2047
+ [name$m]: 'fire-analytics',
2048
+ [name$n]: 'fire-analytics-compat',
2049
+ [name$k]: 'fire-app-check',
2050
+ [name$l]: 'fire-app-check-compat',
2051
+ [name$j]: 'fire-auth',
2052
+ [name$i]: 'fire-auth-compat',
2053
+ [name$h]: 'fire-rtdb',
2054
+ [name$g]: 'fire-rtdb-compat',
2055
+ [name$f]: 'fire-fn',
2056
+ [name$e]: 'fire-fn-compat',
2057
+ [name$d]: 'fire-iid',
2058
+ [name$c]: 'fire-iid-compat',
2059
+ [name$b]: 'fire-fcm',
2060
+ [name$a]: 'fire-fcm-compat',
2061
+ [name$9]: 'fire-perf',
2062
+ [name$8]: 'fire-perf-compat',
2063
+ [name$7]: 'fire-rc',
2064
+ [name$6]: 'fire-rc-compat',
2065
+ [name$5]: 'fire-gcs',
2066
+ [name$4]: 'fire-gcs-compat',
2067
+ [name$3]: 'fire-fst',
2066
2068
  [name$1$1]: 'fire-fst-compat',
2069
+ [name$2]: 'fire-vertex',
2067
2070
  'fire-js': 'fire-js',
2068
- [name$p]: 'fire-js-all'
2071
+ [name$q]: 'fire-js-all'
2069
2072
  };
2070
2073
 
2071
2074
  /**
@@ -2088,6 +2091,10 @@ const PLATFORM_LOG_STRING = {
2088
2091
  * @internal
2089
2092
  */
2090
2093
  const _apps = new Map();
2094
+ /**
2095
+ * @internal
2096
+ */
2097
+ const _serverApps = new Map();
2091
2098
  /**
2092
2099
  * Registered components.
2093
2100
  *
@@ -2126,6 +2133,9 @@ function _registerComponent(component) {
2126
2133
  for (const app of _apps.values()) {
2127
2134
  _addComponent(app, component);
2128
2135
  }
2136
+ for (const serverApp of _serverApps.values()) {
2137
+ _addComponent(serverApp, component);
2138
+ }
2129
2139
  return true;
2130
2140
  }
2131
2141
  /**
@@ -2146,6 +2156,17 @@ function _getProvider(app, name) {
2146
2156
  }
2147
2157
  return app.container.getProvider(name);
2148
2158
  }
2159
+ /**
2160
+ *
2161
+ * @param obj - an object of type FirebaseApp.
2162
+ *
2163
+ * @returns true if the provided object is of type FirebaseServerAppImpl.
2164
+ *
2165
+ * @internal
2166
+ */
2167
+ function _isFirebaseServerApp(obj) {
2168
+ return obj.settings !== undefined;
2169
+ }
2149
2170
 
2150
2171
  /**
2151
2172
  * @license
@@ -2166,9 +2187,10 @@ function _getProvider(app, name) {
2166
2187
  const ERRORS = {
2167
2188
  ["no-app" /* AppError.NO_APP */]: "No Firebase App '{$appName}' has been created - " +
2168
2189
  'call initializeApp() first',
2169
- ["bad-app-name" /* AppError.BAD_APP_NAME */]: "Illegal App name: '{$appName}",
2190
+ ["bad-app-name" /* AppError.BAD_APP_NAME */]: "Illegal App name: '{$appName}'",
2170
2191
  ["duplicate-app" /* AppError.DUPLICATE_APP */]: "Firebase App named '{$appName}' already exists with different options or config",
2171
2192
  ["app-deleted" /* AppError.APP_DELETED */]: "Firebase App named '{$appName}' already deleted",
2193
+ ["server-app-deleted" /* AppError.SERVER_APP_DELETED */]: 'Firebase Server App has been deleted',
2172
2194
  ["no-options" /* AppError.NO_OPTIONS */]: 'Need to provide options, when not being deployed to hosting via source.',
2173
2195
  ["invalid-app-argument" /* AppError.INVALID_APP_ARGUMENT */]: 'firebase.{$appName}() takes either no argument or a ' +
2174
2196
  'Firebase App instance.',
@@ -2176,7 +2198,9 @@ const ERRORS = {
2176
2198
  ["idb-open" /* AppError.IDB_OPEN */]: 'Error thrown when opening IndexedDB. Original error: {$originalErrorMessage}.',
2177
2199
  ["idb-get" /* AppError.IDB_GET */]: 'Error thrown when reading from IndexedDB. Original error: {$originalErrorMessage}.',
2178
2200
  ["idb-set" /* AppError.IDB_WRITE */]: 'Error thrown when writing to IndexedDB. Original error: {$originalErrorMessage}.',
2179
- ["idb-delete" /* AppError.IDB_DELETE */]: 'Error thrown when deleting from IndexedDB. Original error: {$originalErrorMessage}.'
2201
+ ["idb-delete" /* AppError.IDB_DELETE */]: 'Error thrown when deleting from IndexedDB. Original error: {$originalErrorMessage}.',
2202
+ ["finalization-registry-not-supported" /* AppError.FINALIZATION_REGISTRY_NOT_SUPPORTED */]: 'FirebaseServerApp deleteOnDeref field defined but the JS runtime does not support FinalizationRegistry.',
2203
+ ["invalid-server-app-environment" /* AppError.INVALID_SERVER_APP_ENVIRONMENT */]: 'FirebaseServerApp is not for use in browser environments.'
2180
2204
  };
2181
2205
  const ERROR_FACTORY = new ErrorFactory$1('app', 'Firebase', ERRORS);
2182
2206
 
@@ -2412,7 +2436,15 @@ function getDbPromise() {
2412
2436
  // eslint-disable-next-line default-case
2413
2437
  switch (oldVersion) {
2414
2438
  case 0:
2415
- db.createObjectStore(STORE_NAME);
2439
+ try {
2440
+ db.createObjectStore(STORE_NAME);
2441
+ }
2442
+ catch (e) {
2443
+ // Safari/iOS browsers throw occasional exceptions on
2444
+ // db.createObjectStore() that may be a bug. Avoid blocking
2445
+ // the rest of the app functionality.
2446
+ console.warn(e);
2447
+ }
2416
2448
  }
2417
2449
  }
2418
2450
  }).catch(e => {
@@ -2426,10 +2458,11 @@ function getDbPromise() {
2426
2458
  async function readHeartbeatsFromIndexedDB(app) {
2427
2459
  try {
2428
2460
  const db = await getDbPromise();
2429
- const result = await db
2430
- .transaction(STORE_NAME)
2431
- .objectStore(STORE_NAME)
2432
- .get(computeKey(app));
2461
+ const tx = db.transaction(STORE_NAME);
2462
+ const result = await tx.objectStore(STORE_NAME).get(computeKey(app));
2463
+ // We already have the value but tx.done can throw,
2464
+ // so we need to await it here to catch errors
2465
+ await tx.done;
2433
2466
  return result;
2434
2467
  }
2435
2468
  catch (e) {
@@ -2515,33 +2548,45 @@ class HeartbeatServiceImpl {
2515
2548
  * already logged, subsequent calls to this function in the same day will be ignored.
2516
2549
  */
2517
2550
  async triggerHeartbeat() {
2518
- const platformLogger = this.container
2519
- .getProvider('platform-logger')
2520
- .getImmediate();
2521
- // This is the "Firebase user agent" string from the platform logger
2522
- // service, not the browser user agent.
2523
- const agent = platformLogger.getPlatformInfoString();
2524
- const date = getUTCDateString();
2525
- if (this._heartbeatsCache === null) {
2526
- this._heartbeatsCache = await this._heartbeatsCachePromise;
2527
- }
2528
- // Do not store a heartbeat if one is already stored for this day
2529
- // or if a header has already been sent today.
2530
- if (this._heartbeatsCache.lastSentHeartbeatDate === date ||
2531
- this._heartbeatsCache.heartbeats.some(singleDateHeartbeat => singleDateHeartbeat.date === date)) {
2532
- return;
2551
+ var _a, _b, _c;
2552
+ try {
2553
+ const platformLogger = this.container
2554
+ .getProvider('platform-logger')
2555
+ .getImmediate();
2556
+ // This is the "Firebase user agent" string from the platform logger
2557
+ // service, not the browser user agent.
2558
+ const agent = platformLogger.getPlatformInfoString();
2559
+ const date = getUTCDateString();
2560
+ console.log('heartbeats', (_a = this._heartbeatsCache) === null || _a === void 0 ? void 0 : _a.heartbeats);
2561
+ if (((_b = this._heartbeatsCache) === null || _b === void 0 ? void 0 : _b.heartbeats) == null) {
2562
+ this._heartbeatsCache = await this._heartbeatsCachePromise;
2563
+ // If we failed to construct a heartbeats cache, then return immediately.
2564
+ if (((_c = this._heartbeatsCache) === null || _c === void 0 ? void 0 : _c.heartbeats) == null) {
2565
+ return;
2566
+ }
2567
+ }
2568
+ // Do not store a heartbeat if one is already stored for this day
2569
+ // or if a header has already been sent today.
2570
+ if (this._heartbeatsCache.lastSentHeartbeatDate === date ||
2571
+ this._heartbeatsCache.heartbeats.some(singleDateHeartbeat => singleDateHeartbeat.date === date)) {
2572
+ return;
2573
+ }
2574
+ else {
2575
+ // There is no entry for this date. Create one.
2576
+ this._heartbeatsCache.heartbeats.push({ date, agent });
2577
+ }
2578
+ // Remove entries older than 30 days.
2579
+ this._heartbeatsCache.heartbeats =
2580
+ this._heartbeatsCache.heartbeats.filter(singleDateHeartbeat => {
2581
+ const hbTimestamp = new Date(singleDateHeartbeat.date).valueOf();
2582
+ const now = Date.now();
2583
+ return now - hbTimestamp <= STORED_HEARTBEAT_RETENTION_MAX_MILLIS;
2584
+ });
2585
+ return this._storage.overwrite(this._heartbeatsCache);
2586
+ }
2587
+ catch (e) {
2588
+ logger.warn(e);
2533
2589
  }
2534
- else {
2535
- // There is no entry for this date. Create one.
2536
- this._heartbeatsCache.heartbeats.push({ date, agent });
2537
- }
2538
- // Remove entries older than 30 days.
2539
- this._heartbeatsCache.heartbeats = this._heartbeatsCache.heartbeats.filter(singleDateHeartbeat => {
2540
- const hbTimestamp = new Date(singleDateHeartbeat.date).valueOf();
2541
- const now = Date.now();
2542
- return now - hbTimestamp <= STORED_HEARTBEAT_RETENTION_MAX_MILLIS;
2543
- });
2544
- return this._storage.overwrite(this._heartbeatsCache);
2545
2590
  }
2546
2591
  /**
2547
2592
  * Returns a base64 encoded string which can be attached to the heartbeat-specific header directly.
@@ -2551,34 +2596,41 @@ class HeartbeatServiceImpl {
2551
2596
  * returns an empty string.
2552
2597
  */
2553
2598
  async getHeartbeatsHeader() {
2554
- if (this._heartbeatsCache === null) {
2555
- await this._heartbeatsCachePromise;
2599
+ var _a;
2600
+ try {
2601
+ if (this._heartbeatsCache === null) {
2602
+ await this._heartbeatsCachePromise;
2603
+ }
2604
+ // If it's still null or the array is empty, there is no data to send.
2605
+ if (((_a = this._heartbeatsCache) === null || _a === void 0 ? void 0 : _a.heartbeats) == null ||
2606
+ this._heartbeatsCache.heartbeats.length === 0) {
2607
+ return '';
2608
+ }
2609
+ const date = getUTCDateString();
2610
+ // Extract as many heartbeats from the cache as will fit under the size limit.
2611
+ const { heartbeatsToSend, unsentEntries } = extractHeartbeatsForHeader(this._heartbeatsCache.heartbeats);
2612
+ const headerString = base64urlEncodeWithoutPadding$1(JSON.stringify({ version: 2, heartbeats: heartbeatsToSend }));
2613
+ // Store last sent date to prevent another being logged/sent for the same day.
2614
+ this._heartbeatsCache.lastSentHeartbeatDate = date;
2615
+ if (unsentEntries.length > 0) {
2616
+ // Store any unsent entries if they exist.
2617
+ this._heartbeatsCache.heartbeats = unsentEntries;
2618
+ // This seems more likely than emptying the array (below) to lead to some odd state
2619
+ // since the cache isn't empty and this will be called again on the next request,
2620
+ // and is probably safest if we await it.
2621
+ await this._storage.overwrite(this._heartbeatsCache);
2622
+ }
2623
+ else {
2624
+ this._heartbeatsCache.heartbeats = [];
2625
+ // Do not wait for this, to reduce latency.
2626
+ void this._storage.overwrite(this._heartbeatsCache);
2627
+ }
2628
+ return headerString;
2556
2629
  }
2557
- // If it's still null or the array is empty, there is no data to send.
2558
- if (this._heartbeatsCache === null ||
2559
- this._heartbeatsCache.heartbeats.length === 0) {
2630
+ catch (e) {
2631
+ logger.warn(e);
2560
2632
  return '';
2561
2633
  }
2562
- const date = getUTCDateString();
2563
- // Extract as many heartbeats from the cache as will fit under the size limit.
2564
- const { heartbeatsToSend, unsentEntries } = extractHeartbeatsForHeader(this._heartbeatsCache.heartbeats);
2565
- const headerString = base64urlEncodeWithoutPadding$1(JSON.stringify({ version: 2, heartbeats: heartbeatsToSend }));
2566
- // Store last sent date to prevent another being logged/sent for the same day.
2567
- this._heartbeatsCache.lastSentHeartbeatDate = date;
2568
- if (unsentEntries.length > 0) {
2569
- // Store any unsent entries if they exist.
2570
- this._heartbeatsCache.heartbeats = unsentEntries;
2571
- // This seems more likely than emptying the array (below) to lead to some odd state
2572
- // since the cache isn't empty and this will be called again on the next request,
2573
- // and is probably safest if we await it.
2574
- await this._storage.overwrite(this._heartbeatsCache);
2575
- }
2576
- else {
2577
- this._heartbeatsCache.heartbeats = [];
2578
- // Do not wait for this, to reduce latency.
2579
- void this._storage.overwrite(this._heartbeatsCache);
2580
- }
2581
- return headerString;
2582
2634
  }
2583
2635
  }
2584
2636
  function getUTCDateString() {
@@ -2651,7 +2703,12 @@ class HeartbeatStorageImpl {
2651
2703
  }
2652
2704
  else {
2653
2705
  const idbHeartbeatObject = await readHeartbeatsFromIndexedDB(this.app);
2654
- return idbHeartbeatObject || { heartbeats: [] };
2706
+ if (idbHeartbeatObject === null || idbHeartbeatObject === void 0 ? void 0 : idbHeartbeatObject.heartbeats) {
2707
+ return idbHeartbeatObject;
2708
+ }
2709
+ else {
2710
+ return { heartbeats: [] };
2711
+ }
2655
2712
  }
2656
2713
  }
2657
2714
  // overwrite the storage with the provided heartbeats
@@ -2720,9 +2777,9 @@ function registerCoreComponents(variant) {
2720
2777
  _registerComponent(new Component$1('platform-logger', container => new PlatformLoggerServiceImpl(container), "PRIVATE" /* ComponentType.PRIVATE */));
2721
2778
  _registerComponent(new Component$1('heartbeat', container => new HeartbeatServiceImpl(container), "PRIVATE" /* ComponentType.PRIVATE */));
2722
2779
  // Register `app` package.
2723
- registerVersion(name$o, version$1$1, variant);
2780
+ registerVersion(name$p, version$1$1, variant);
2724
2781
  // BUILD_TARGET will be replaced by values like esm5, esm2017, cjs5, etc during the compilation
2725
- registerVersion(name$o, version$1$1, 'esm2017');
2782
+ registerVersion(name$p, version$1$1, 'esm2017');
2726
2783
  // Register platform SDK identifier (no version).
2727
2784
  registerVersion('fire-js', '');
2728
2785
  }
@@ -17789,7 +17846,7 @@ function jl(t, ...e) {
17789
17846
  }();
17790
17847
 
17791
17848
  var name$1 = "firebase";
17792
- var version$1 = "9.23.0";
17849
+ var version$1 = "10.13.0";
17793
17850
 
17794
17851
  /**
17795
17852
  * @license
@@ -18605,6 +18662,7 @@ const AUTH_ERROR_CODES_MAP_DO_NOT_USE_INTERNALLY = {
18605
18662
  INVALID_EMAIL: 'auth/invalid-email',
18606
18663
  INVALID_EMULATOR_SCHEME: 'auth/invalid-emulator-scheme',
18607
18664
  INVALID_IDP_RESPONSE: 'auth/invalid-credential',
18665
+ INVALID_LOGIN_CREDENTIALS: 'auth/invalid-credential',
18608
18666
  INVALID_MESSAGE_PAYLOAD: 'auth/invalid-message-payload',
18609
18667
  INVALID_MFA_SESSION: 'auth/invalid-multi-factor-session',
18610
18668
  INVALID_OAUTH_CLIENT_ID: 'auth/invalid-oauth-client-id',
@@ -18734,6 +18792,9 @@ function _errorWithCustomMessage(auth, code, message) {
18734
18792
  appName: auth.name
18735
18793
  });
18736
18794
  }
18795
+ function _serverAppCurrentUserOperationNotSupportedError(auth) {
18796
+ return _errorWithCustomMessage(auth, "operation-not-supported-in-this-environment" /* AuthErrorCode.OPERATION_NOT_SUPPORTED */, 'Operations that alter the current user are not supported in conjunction with FirebaseServerApp');
18797
+ }
18737
18798
  function createErrorInternal(authOrCode, ...rest) {
18738
18799
  if (typeof authOrCode !== 'string') {
18739
18800
  const code = rest[0];
@@ -18957,6 +19018,12 @@ class FetchProvider {
18957
19018
  if (typeof self !== 'undefined' && 'fetch' in self) {
18958
19019
  return self.fetch;
18959
19020
  }
19021
+ if (typeof globalThis !== 'undefined' && globalThis.fetch) {
19022
+ return globalThis.fetch;
19023
+ }
19024
+ if (typeof fetch !== 'undefined') {
19025
+ return fetch;
19026
+ }
18960
19027
  debugFail('Could not find fetch implementation, make sure you call FetchProvider.initialize() with an appropriate polyfill');
18961
19028
  }
18962
19029
  static headers() {
@@ -18966,6 +19033,12 @@ class FetchProvider {
18966
19033
  if (typeof self !== 'undefined' && 'Headers' in self) {
18967
19034
  return self.Headers;
18968
19035
  }
19036
+ if (typeof globalThis !== 'undefined' && globalThis.Headers) {
19037
+ return globalThis.Headers;
19038
+ }
19039
+ if (typeof Headers !== 'undefined') {
19040
+ return Headers;
19041
+ }
18969
19042
  debugFail('Could not find Headers implementation, make sure you call FetchProvider.initialize() with an appropriate polyfill');
18970
19043
  }
18971
19044
  static response() {
@@ -18975,6 +19048,12 @@ class FetchProvider {
18975
19048
  if (typeof self !== 'undefined' && 'Response' in self) {
18976
19049
  return self.Response;
18977
19050
  }
19051
+ if (typeof globalThis !== 'undefined' && globalThis.Response) {
19052
+ return globalThis.Response;
19053
+ }
19054
+ if (typeof Response !== 'undefined') {
19055
+ return Response;
19056
+ }
18978
19057
  debugFail('Could not find Response implementation, make sure you call FetchProvider.initialize() with an appropriate polyfill');
18979
19058
  }
18980
19059
  }
@@ -19011,12 +19090,15 @@ const SERVER_ERROR_MAP = {
19011
19090
  ["INVALID_PASSWORD" /* ServerError.INVALID_PASSWORD */]: "wrong-password" /* AuthErrorCode.INVALID_PASSWORD */,
19012
19091
  // This can only happen if the SDK sends a bad request.
19013
19092
  ["MISSING_PASSWORD" /* ServerError.MISSING_PASSWORD */]: "missing-password" /* AuthErrorCode.MISSING_PASSWORD */,
19093
+ // Thrown if Email Enumeration Protection is enabled in the project and the email or password is
19094
+ // invalid.
19095
+ ["INVALID_LOGIN_CREDENTIALS" /* ServerError.INVALID_LOGIN_CREDENTIALS */]: "invalid-credential" /* AuthErrorCode.INVALID_CREDENTIAL */,
19014
19096
  // Sign up with email and password errors.
19015
19097
  ["EMAIL_EXISTS" /* ServerError.EMAIL_EXISTS */]: "email-already-in-use" /* AuthErrorCode.EMAIL_EXISTS */,
19016
19098
  ["PASSWORD_LOGIN_DISABLED" /* ServerError.PASSWORD_LOGIN_DISABLED */]: "operation-not-allowed" /* AuthErrorCode.OPERATION_NOT_ALLOWED */,
19017
19099
  // Verify assertion for sign in with credential errors:
19018
- ["INVALID_IDP_RESPONSE" /* ServerError.INVALID_IDP_RESPONSE */]: "invalid-credential" /* AuthErrorCode.INVALID_IDP_RESPONSE */,
19019
- ["INVALID_PENDING_TOKEN" /* ServerError.INVALID_PENDING_TOKEN */]: "invalid-credential" /* AuthErrorCode.INVALID_IDP_RESPONSE */,
19100
+ ["INVALID_IDP_RESPONSE" /* ServerError.INVALID_IDP_RESPONSE */]: "invalid-credential" /* AuthErrorCode.INVALID_CREDENTIAL */,
19101
+ ["INVALID_PENDING_TOKEN" /* ServerError.INVALID_PENDING_TOKEN */]: "invalid-credential" /* AuthErrorCode.INVALID_CREDENTIAL */,
19020
19102
  ["FEDERATED_USER_ID_ALREADY_LINKED" /* ServerError.FEDERATED_USER_ID_ALREADY_LINKED */]: "credential-already-in-use" /* AuthErrorCode.CREDENTIAL_ALREADY_IN_USE */,
19021
19103
  // This can only happen if the SDK sends a bad request.
19022
19104
  ["MISSING_REQ_TYPE" /* ServerError.MISSING_REQ_TYPE */]: "internal-error" /* AuthErrorCode.INTERNAL_ERROR */,
@@ -19034,10 +19116,11 @@ const SERVER_ERROR_MAP = {
19034
19116
  ["USER_NOT_FOUND" /* ServerError.USER_NOT_FOUND */]: "user-token-expired" /* AuthErrorCode.TOKEN_EXPIRED */,
19035
19117
  // Other errors.
19036
19118
  ["TOO_MANY_ATTEMPTS_TRY_LATER" /* ServerError.TOO_MANY_ATTEMPTS_TRY_LATER */]: "too-many-requests" /* AuthErrorCode.TOO_MANY_ATTEMPTS_TRY_LATER */,
19119
+ ["PASSWORD_DOES_NOT_MEET_REQUIREMENTS" /* ServerError.PASSWORD_DOES_NOT_MEET_REQUIREMENTS */]: "password-does-not-meet-requirements" /* AuthErrorCode.PASSWORD_DOES_NOT_MEET_REQUIREMENTS */,
19037
19120
  // Phone Auth related errors.
19038
19121
  ["INVALID_CODE" /* ServerError.INVALID_CODE */]: "invalid-verification-code" /* AuthErrorCode.INVALID_CODE */,
19039
19122
  ["INVALID_SESSION_INFO" /* ServerError.INVALID_SESSION_INFO */]: "invalid-verification-id" /* AuthErrorCode.INVALID_SESSION_INFO */,
19040
- ["INVALID_TEMPORARY_PROOF" /* ServerError.INVALID_TEMPORARY_PROOF */]: "invalid-credential" /* AuthErrorCode.INVALID_IDP_RESPONSE */,
19123
+ ["INVALID_TEMPORARY_PROOF" /* ServerError.INVALID_TEMPORARY_PROOF */]: "invalid-credential" /* AuthErrorCode.INVALID_CREDENTIAL */,
19041
19124
  ["MISSING_SESSION_INFO" /* ServerError.MISSING_SESSION_INFO */]: "missing-verification-id" /* AuthErrorCode.MISSING_SESSION_INFO */,
19042
19125
  ["SESSION_EXPIRED" /* ServerError.SESSION_EXPIRED */]: "code-expired" /* AuthErrorCode.CODE_EXPIRED */,
19043
19126
  // Other action code errors when additional settings passed.
@@ -19185,6 +19268,18 @@ function _getFinalTarget(auth, host, path, query) {
19185
19268
  }
19186
19269
  return _emulatorUrl(auth.config, base);
19187
19270
  }
19271
+ function _parseEnforcementState(enforcementStateStr) {
19272
+ switch (enforcementStateStr) {
19273
+ case 'ENFORCE':
19274
+ return "ENFORCE" /* EnforcementState.ENFORCE */;
19275
+ case 'AUDIT':
19276
+ return "AUDIT" /* EnforcementState.AUDIT */;
19277
+ case 'OFF':
19278
+ return "OFF" /* EnforcementState.OFF */;
19279
+ default:
19280
+ return "ENFORCEMENT_STATE_UNSPECIFIED" /* EnforcementState.ENFORCEMENT_STATE_UNSPECIFIED */;
19281
+ }
19282
+ }
19188
19283
  class NetworkTimeout {
19189
19284
  constructor(auth) {
19190
19285
  this.auth = auth;
@@ -19217,6 +19312,61 @@ function _makeTaggedError(auth, code, response) {
19217
19312
  error.customData._tokenResponse = response;
19218
19313
  return error;
19219
19314
  }
19315
+ function isEnterprise(grecaptcha) {
19316
+ return (grecaptcha !== undefined &&
19317
+ grecaptcha.enterprise !== undefined);
19318
+ }
19319
+ class RecaptchaConfig {
19320
+ constructor(response) {
19321
+ /**
19322
+ * The reCAPTCHA site key.
19323
+ */
19324
+ this.siteKey = '';
19325
+ /**
19326
+ * The list of providers and their enablement status for reCAPTCHA Enterprise.
19327
+ */
19328
+ this.recaptchaEnforcementState = [];
19329
+ if (response.recaptchaKey === undefined) {
19330
+ throw new Error('recaptchaKey undefined');
19331
+ }
19332
+ // Example response.recaptchaKey: "projects/proj123/keys/sitekey123"
19333
+ this.siteKey = response.recaptchaKey.split('/')[3];
19334
+ this.recaptchaEnforcementState = response.recaptchaEnforcementState;
19335
+ }
19336
+ /**
19337
+ * Returns the reCAPTCHA Enterprise enforcement state for the given provider.
19338
+ *
19339
+ * @param providerStr - The provider whose enforcement state is to be returned.
19340
+ * @returns The reCAPTCHA Enterprise enforcement state for the given provider.
19341
+ */
19342
+ getProviderEnforcementState(providerStr) {
19343
+ if (!this.recaptchaEnforcementState ||
19344
+ this.recaptchaEnforcementState.length === 0) {
19345
+ return null;
19346
+ }
19347
+ for (const recaptchaEnforcementState of this.recaptchaEnforcementState) {
19348
+ if (recaptchaEnforcementState.provider &&
19349
+ recaptchaEnforcementState.provider === providerStr) {
19350
+ return _parseEnforcementState(recaptchaEnforcementState.enforcementState);
19351
+ }
19352
+ }
19353
+ return null;
19354
+ }
19355
+ /**
19356
+ * Returns true if the reCAPTCHA Enterprise enforcement state for the provider is set to ENFORCE or AUDIT.
19357
+ *
19358
+ * @param providerStr - The provider whose enablement state is to be returned.
19359
+ * @returns Whether or not reCAPTCHA Enterprise protection is enabled for the given provider.
19360
+ */
19361
+ isProviderEnabled(providerStr) {
19362
+ return (this.getProviderEnforcementState(providerStr) ===
19363
+ "ENFORCE" /* EnforcementState.ENFORCE */ ||
19364
+ this.getProviderEnforcementState(providerStr) === "AUDIT" /* EnforcementState.AUDIT */);
19365
+ }
19366
+ }
19367
+ async function getRecaptchaConfig(auth, request) {
19368
+ return _performApiRequest(auth, "GET" /* HttpMethod.GET */, "/v2/recaptchaConfig" /* Endpoint.GET_RECAPTCHA_CONFIG */, _addTidIfNecessary(auth, request));
19369
+ }
19220
19370
 
19221
19371
  /**
19222
19372
  * @license
@@ -19621,6 +19771,9 @@ async function requestStsToken(auth, refreshToken) {
19621
19771
  expiresIn: response.expires_in,
19622
19772
  refreshToken: response.refresh_token
19623
19773
  };
19774
+ }
19775
+ async function revokeToken(auth, request) {
19776
+ return _performApiRequest(auth, "POST" /* HttpMethod.POST */, "/v2/accounts:revokeToken" /* Endpoint.REVOKE_TOKEN */, _addTidIfNecessary(auth, request));
19624
19777
  }
19625
19778
 
19626
19779
  /**
@@ -19664,11 +19817,16 @@ class StsTokenManager {
19664
19817
  : _tokenExpiresIn(response.idToken);
19665
19818
  this.updateTokensAndExpiration(response.idToken, response.refreshToken, expiresIn);
19666
19819
  }
19820
+ updateFromIdToken(idToken) {
19821
+ _assert(idToken.length !== 0, "internal-error" /* AuthErrorCode.INTERNAL_ERROR */);
19822
+ const expiresIn = _tokenExpiresIn(idToken);
19823
+ this.updateTokensAndExpiration(idToken, null, expiresIn);
19824
+ }
19667
19825
  async getToken(auth, forceRefresh = false) {
19668
- _assert(!this.accessToken || this.refreshToken, auth, "user-token-expired" /* AuthErrorCode.TOKEN_EXPIRED */);
19669
19826
  if (!forceRefresh && this.accessToken && !this.isExpired) {
19670
19827
  return this.accessToken;
19671
19828
  }
19829
+ _assert(this.refreshToken, auth, "user-token-expired" /* AuthErrorCode.TOKEN_EXPIRED */);
19672
19830
  if (this.refreshToken) {
19673
19831
  await this.refresh(auth, this.refreshToken);
19674
19832
  return this.accessToken;
@@ -19848,6 +20006,9 @@ class UserImpl {
19848
20006
  }
19849
20007
  }
19850
20008
  async delete() {
20009
+ if (_isFirebaseServerApp(this.auth.app)) {
20010
+ return Promise.reject(_serverAppCurrentUserOperationNotSupportedError(this.auth));
20011
+ }
19851
20012
  const idToken = await this.getIdToken();
19852
20013
  await _logoutIfInvalidated(this, deleteAccount(this.auth, { idToken }));
19853
20014
  this.stsTokenManager.clearRefreshToken();
@@ -19931,6 +20092,44 @@ class UserImpl {
19931
20092
  await _reloadWithoutSaving(user);
19932
20093
  return user;
19933
20094
  }
20095
+ /**
20096
+ * Initialize a User from an idToken server response
20097
+ * @param auth
20098
+ * @param idTokenResponse
20099
+ */
20100
+ static async _fromGetAccountInfoResponse(auth, response, idToken) {
20101
+ const coreAccount = response.users[0];
20102
+ _assert(coreAccount.localId !== undefined, "internal-error" /* AuthErrorCode.INTERNAL_ERROR */);
20103
+ const providerData = coreAccount.providerUserInfo !== undefined
20104
+ ? extractProviderData(coreAccount.providerUserInfo)
20105
+ : [];
20106
+ const isAnonymous = !(coreAccount.email && coreAccount.passwordHash) && !(providerData === null || providerData === void 0 ? void 0 : providerData.length);
20107
+ const stsTokenManager = new StsTokenManager();
20108
+ stsTokenManager.updateFromIdToken(idToken);
20109
+ // Initialize the Firebase Auth user.
20110
+ const user = new UserImpl({
20111
+ uid: coreAccount.localId,
20112
+ auth,
20113
+ stsTokenManager,
20114
+ isAnonymous
20115
+ });
20116
+ // update the user with data from the GetAccountInfo response.
20117
+ const updates = {
20118
+ uid: coreAccount.localId,
20119
+ displayName: coreAccount.displayName || null,
20120
+ photoURL: coreAccount.photoUrl || null,
20121
+ email: coreAccount.email || null,
20122
+ emailVerified: coreAccount.emailVerified || false,
20123
+ phoneNumber: coreAccount.phoneNumber || null,
20124
+ tenantId: coreAccount.tenantId || null,
20125
+ providerData,
20126
+ metadata: new UserMetadata(coreAccount.createdAt, coreAccount.lastLoginAt),
20127
+ isAnonymous: !(coreAccount.email && coreAccount.passwordHash) &&
20128
+ !(providerData === null || providerData === void 0 ? void 0 : providerData.length)
20129
+ };
20130
+ Object.assign(user, updates);
20131
+ return user;
20132
+ }
19934
20133
  }
19935
20134
 
19936
20135
  /**
@@ -20246,16 +20445,6 @@ function _isMobileBrowser(ua = getUA()) {
20246
20445
  _isBlackBerry(ua) ||
20247
20446
  /windows phone/i.test(ua) ||
20248
20447
  _isIEMobile(ua));
20249
- }
20250
- function _isIframe() {
20251
- try {
20252
- // Check that the current window is not the top window.
20253
- // If so, return true.
20254
- return !!(window && window !== window.top);
20255
- }
20256
- catch (e) {
20257
- return false;
20258
- }
20259
20448
  }
20260
20449
 
20261
20450
  /**
@@ -20298,36 +20487,91 @@ function _getClientVersion(clientPlatform, frameworks = []) {
20298
20487
  : 'FirebaseCore-web'; /* default value if no other framework is used */
20299
20488
  return `${reportedPlatform}/${"JsCore" /* ClientImplementation.CORE */}/${SDK_VERSION}/${reportedFrameworks}`;
20300
20489
  }
20301
- async function getRecaptchaConfig(auth, request) {
20302
- return _performApiRequest(auth, "GET" /* HttpMethod.GET */, "/v2/recaptchaConfig" /* Endpoint.GET_RECAPTCHA_CONFIG */, _addTidIfNecessary(auth, request));
20303
- }
20304
- function isEnterprise(grecaptcha) {
20305
- return (grecaptcha !== undefined &&
20306
- grecaptcha.enterprise !== undefined);
20307
- }
20308
- class RecaptchaConfig {
20309
- constructor(response) {
20310
- /**
20311
- * The reCAPTCHA site key.
20312
- */
20313
- this.siteKey = '';
20314
- /**
20315
- * The reCAPTCHA enablement status of the {@link EmailAuthProvider} for the current tenant.
20316
- */
20317
- this.emailPasswordEnabled = false;
20318
- if (response.recaptchaKey === undefined) {
20319
- throw new Error('recaptchaKey undefined');
20490
+
20491
+ /**
20492
+ * @license
20493
+ * Copyright 2022 Google LLC
20494
+ *
20495
+ * Licensed under the Apache License, Version 2.0 (the "License");
20496
+ * you may not use this file except in compliance with the License.
20497
+ * You may obtain a copy of the License at
20498
+ *
20499
+ * http://www.apache.org/licenses/LICENSE-2.0
20500
+ *
20501
+ * Unless required by applicable law or agreed to in writing, software
20502
+ * distributed under the License is distributed on an "AS IS" BASIS,
20503
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20504
+ * See the License for the specific language governing permissions and
20505
+ * limitations under the License.
20506
+ */
20507
+ class AuthMiddlewareQueue {
20508
+ constructor(auth) {
20509
+ this.auth = auth;
20510
+ this.queue = [];
20511
+ }
20512
+ pushCallback(callback, onAbort) {
20513
+ // The callback could be sync or async. Wrap it into a
20514
+ // function that is always async.
20515
+ const wrappedCallback = (user) => new Promise((resolve, reject) => {
20516
+ try {
20517
+ const result = callback(user);
20518
+ // Either resolve with existing promise or wrap a non-promise
20519
+ // return value into a promise.
20520
+ resolve(result);
20521
+ }
20522
+ catch (e) {
20523
+ // Sync callback throws.
20524
+ reject(e);
20525
+ }
20526
+ });
20527
+ // Attach the onAbort if present
20528
+ wrappedCallback.onAbort = onAbort;
20529
+ this.queue.push(wrappedCallback);
20530
+ const index = this.queue.length - 1;
20531
+ return () => {
20532
+ // Unsubscribe. Replace with no-op. Do not remove from array, or it will disturb
20533
+ // indexing of other elements.
20534
+ this.queue[index] = () => Promise.resolve();
20535
+ };
20536
+ }
20537
+ async runMiddleware(nextUser) {
20538
+ if (this.auth.currentUser === nextUser) {
20539
+ return;
20540
+ }
20541
+ // While running the middleware, build a temporary stack of onAbort
20542
+ // callbacks to call if one middleware callback rejects.
20543
+ const onAbortStack = [];
20544
+ try {
20545
+ for (const beforeStateCallback of this.queue) {
20546
+ await beforeStateCallback(nextUser);
20547
+ // Only push the onAbort if the callback succeeds
20548
+ if (beforeStateCallback.onAbort) {
20549
+ onAbortStack.push(beforeStateCallback.onAbort);
20550
+ }
20551
+ }
20552
+ }
20553
+ catch (e) {
20554
+ // Run all onAbort, with separate try/catch to ignore any errors and
20555
+ // continue
20556
+ onAbortStack.reverse();
20557
+ for (const onAbort of onAbortStack) {
20558
+ try {
20559
+ onAbort();
20560
+ }
20561
+ catch (_) {
20562
+ /* swallow error */
20563
+ }
20564
+ }
20565
+ throw this.auth._errorFactory.create("login-blocked" /* AuthErrorCode.LOGIN_BLOCKED */, {
20566
+ originalMessage: e === null || e === void 0 ? void 0 : e.message
20567
+ });
20320
20568
  }
20321
- // Example response.recaptchaKey: "projects/proj123/keys/sitekey123"
20322
- this.siteKey = response.recaptchaKey.split('/')[3];
20323
- this.emailPasswordEnabled = response.recaptchaEnforcementState.some(enforcementState => enforcementState.provider === 'EMAIL_PASSWORD_PROVIDER' &&
20324
- enforcementState.enforcementState !== 'OFF');
20325
20569
  }
20326
20570
  }
20327
20571
 
20328
20572
  /**
20329
20573
  * @license
20330
- * Copyright 2020 Google LLC
20574
+ * Copyright 2023 Google LLC
20331
20575
  *
20332
20576
  * Licensed under the Apache License, Version 2.0 (the "License");
20333
20577
  * you may not use this file except in compliance with the License.
@@ -20341,232 +20585,162 @@ class RecaptchaConfig {
20341
20585
  * See the License for the specific language governing permissions and
20342
20586
  * limitations under the License.
20343
20587
  */
20344
- function getScriptParentElement() {
20345
- var _a, _b;
20346
- return (_b = (_a = document.getElementsByTagName('head')) === null || _a === void 0 ? void 0 : _a[0]) !== null && _b !== void 0 ? _b : document;
20347
- }
20348
- function _loadJS(url) {
20349
- // TODO: consider adding timeout support & cancellation
20350
- return new Promise((resolve, reject) => {
20351
- const el = document.createElement('script');
20352
- el.setAttribute('src', url);
20353
- el.onload = resolve;
20354
- el.onerror = e => {
20355
- const error = _createError("internal-error" /* AuthErrorCode.INTERNAL_ERROR */);
20356
- error.customData = e;
20357
- reject(error);
20358
- };
20359
- el.type = 'text/javascript';
20360
- el.charset = 'UTF-8';
20361
- getScriptParentElement().appendChild(el);
20362
- });
20363
- }
20364
- function _generateCallbackName(prefix) {
20365
- return `__${prefix}${Math.floor(Math.random() * 1000000)}`;
20588
+ /**
20589
+ * Fetches the password policy for the currently set tenant or the project if no tenant is set.
20590
+ *
20591
+ * @param auth Auth object.
20592
+ * @param request Password policy request.
20593
+ * @returns Password policy response.
20594
+ */
20595
+ async function _getPasswordPolicy(auth, request = {}) {
20596
+ return _performApiRequest(auth, "GET" /* HttpMethod.GET */, "/v2/passwordPolicy" /* Endpoint.GET_PASSWORD_POLICY */, _addTidIfNecessary(auth, request));
20366
20597
  }
20367
20598
 
20368
- /* eslint-disable @typescript-eslint/no-require-imports */
20369
- const RECAPTCHA_ENTERPRISE_URL = 'https://www.google.com/recaptcha/enterprise.js?render=';
20370
- const RECAPTCHA_ENTERPRISE_VERIFIER_TYPE = 'recaptcha-enterprise';
20371
- const FAKE_TOKEN = 'NO_RECAPTCHA';
20372
- class RecaptchaEnterpriseVerifier {
20599
+ /**
20600
+ * @license
20601
+ * Copyright 2023 Google LLC
20602
+ *
20603
+ * Licensed under the Apache License, Version 2.0 (the "License");
20604
+ * you may not use this file except in compliance with the License.
20605
+ * You may obtain a copy of the License at
20606
+ *
20607
+ * http://www.apache.org/licenses/LICENSE-2.0
20608
+ *
20609
+ * Unless required by applicable law or agreed to in writing, software
20610
+ * distributed under the License is distributed on an "AS IS" BASIS,
20611
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20612
+ * See the License for the specific language governing permissions and
20613
+ * limitations under the License.
20614
+ */
20615
+ // Minimum min password length enforced by the backend, even if no minimum length is set.
20616
+ const MINIMUM_MIN_PASSWORD_LENGTH = 6;
20617
+ /**
20618
+ * Stores password policy requirements and provides password validation against the policy.
20619
+ *
20620
+ * @internal
20621
+ */
20622
+ class PasswordPolicyImpl {
20623
+ constructor(response) {
20624
+ var _a, _b, _c, _d;
20625
+ // Only include custom strength options defined in the response.
20626
+ const responseOptions = response.customStrengthOptions;
20627
+ this.customStrengthOptions = {};
20628
+ // TODO: Remove once the backend is updated to include the minimum min password length instead of undefined when there is no minimum length set.
20629
+ this.customStrengthOptions.minPasswordLength =
20630
+ (_a = responseOptions.minPasswordLength) !== null && _a !== void 0 ? _a : MINIMUM_MIN_PASSWORD_LENGTH;
20631
+ if (responseOptions.maxPasswordLength) {
20632
+ this.customStrengthOptions.maxPasswordLength =
20633
+ responseOptions.maxPasswordLength;
20634
+ }
20635
+ if (responseOptions.containsLowercaseCharacter !== undefined) {
20636
+ this.customStrengthOptions.containsLowercaseLetter =
20637
+ responseOptions.containsLowercaseCharacter;
20638
+ }
20639
+ if (responseOptions.containsUppercaseCharacter !== undefined) {
20640
+ this.customStrengthOptions.containsUppercaseLetter =
20641
+ responseOptions.containsUppercaseCharacter;
20642
+ }
20643
+ if (responseOptions.containsNumericCharacter !== undefined) {
20644
+ this.customStrengthOptions.containsNumericCharacter =
20645
+ responseOptions.containsNumericCharacter;
20646
+ }
20647
+ if (responseOptions.containsNonAlphanumericCharacter !== undefined) {
20648
+ this.customStrengthOptions.containsNonAlphanumericCharacter =
20649
+ responseOptions.containsNonAlphanumericCharacter;
20650
+ }
20651
+ this.enforcementState = response.enforcementState;
20652
+ if (this.enforcementState === 'ENFORCEMENT_STATE_UNSPECIFIED') {
20653
+ this.enforcementState = 'OFF';
20654
+ }
20655
+ // Use an empty string if no non-alphanumeric characters are specified in the response.
20656
+ this.allowedNonAlphanumericCharacters =
20657
+ (_c = (_b = response.allowedNonAlphanumericCharacters) === null || _b === void 0 ? void 0 : _b.join('')) !== null && _c !== void 0 ? _c : '';
20658
+ this.forceUpgradeOnSignin = (_d = response.forceUpgradeOnSignin) !== null && _d !== void 0 ? _d : false;
20659
+ this.schemaVersion = response.schemaVersion;
20660
+ }
20661
+ validatePassword(password) {
20662
+ var _a, _b, _c, _d, _e, _f;
20663
+ const status = {
20664
+ isValid: true,
20665
+ passwordPolicy: this
20666
+ };
20667
+ // Check the password length and character options.
20668
+ this.validatePasswordLengthOptions(password, status);
20669
+ this.validatePasswordCharacterOptions(password, status);
20670
+ // Combine the status into single isValid property.
20671
+ status.isValid && (status.isValid = (_a = status.meetsMinPasswordLength) !== null && _a !== void 0 ? _a : true);
20672
+ status.isValid && (status.isValid = (_b = status.meetsMaxPasswordLength) !== null && _b !== void 0 ? _b : true);
20673
+ status.isValid && (status.isValid = (_c = status.containsLowercaseLetter) !== null && _c !== void 0 ? _c : true);
20674
+ status.isValid && (status.isValid = (_d = status.containsUppercaseLetter) !== null && _d !== void 0 ? _d : true);
20675
+ status.isValid && (status.isValid = (_e = status.containsNumericCharacter) !== null && _e !== void 0 ? _e : true);
20676
+ status.isValid && (status.isValid = (_f = status.containsNonAlphanumericCharacter) !== null && _f !== void 0 ? _f : true);
20677
+ return status;
20678
+ }
20373
20679
  /**
20680
+ * Validates that the password meets the length options for the policy.
20374
20681
  *
20375
- * @param authExtern - The corresponding Firebase {@link Auth} instance.
20376
- *
20682
+ * @param password Password to validate.
20683
+ * @param status Validation status.
20377
20684
  */
20378
- constructor(authExtern) {
20379
- /**
20380
- * Identifies the type of application verifier (e.g. "recaptcha-enterprise").
20381
- */
20382
- this.type = RECAPTCHA_ENTERPRISE_VERIFIER_TYPE;
20383
- this.auth = _castAuth(authExtern);
20685
+ validatePasswordLengthOptions(password, status) {
20686
+ const minPasswordLength = this.customStrengthOptions.minPasswordLength;
20687
+ const maxPasswordLength = this.customStrengthOptions.maxPasswordLength;
20688
+ if (minPasswordLength) {
20689
+ status.meetsMinPasswordLength = password.length >= minPasswordLength;
20690
+ }
20691
+ if (maxPasswordLength) {
20692
+ status.meetsMaxPasswordLength = password.length <= maxPasswordLength;
20693
+ }
20384
20694
  }
20385
20695
  /**
20386
- * Executes the verification process.
20696
+ * Validates that the password meets the character options for the policy.
20387
20697
  *
20388
- * @returns A Promise for a token that can be used to assert the validity of a request.
20698
+ * @param password Password to validate.
20699
+ * @param status Validation status.
20389
20700
  */
20390
- async verify(action = 'verify', forceRefresh = false) {
20391
- async function retrieveSiteKey(auth) {
20392
- if (!forceRefresh) {
20393
- if (auth.tenantId == null && auth._agentRecaptchaConfig != null) {
20394
- return auth._agentRecaptchaConfig.siteKey;
20395
- }
20396
- if (auth.tenantId != null &&
20397
- auth._tenantRecaptchaConfigs[auth.tenantId] !== undefined) {
20398
- return auth._tenantRecaptchaConfigs[auth.tenantId].siteKey;
20399
- }
20400
- }
20401
- return new Promise(async (resolve, reject) => {
20402
- getRecaptchaConfig(auth, {
20403
- clientType: "CLIENT_TYPE_WEB" /* RecaptchaClientType.WEB */,
20404
- version: "RECAPTCHA_ENTERPRISE" /* RecaptchaVersion.ENTERPRISE */
20405
- })
20406
- .then(response => {
20407
- if (response.recaptchaKey === undefined) {
20408
- reject(new Error('recaptcha Enterprise site key undefined'));
20409
- }
20410
- else {
20411
- const config = new RecaptchaConfig(response);
20412
- if (auth.tenantId == null) {
20413
- auth._agentRecaptchaConfig = config;
20414
- }
20415
- else {
20416
- auth._tenantRecaptchaConfigs[auth.tenantId] = config;
20417
- }
20418
- return resolve(config.siteKey);
20419
- }
20420
- })
20421
- .catch(error => {
20422
- reject(error);
20423
- });
20424
- });
20701
+ validatePasswordCharacterOptions(password, status) {
20702
+ // Assign statuses for requirements even if the password is an empty string.
20703
+ this.updatePasswordCharacterOptionsStatuses(status,
20704
+ /* containsLowercaseCharacter= */ false,
20705
+ /* containsUppercaseCharacter= */ false,
20706
+ /* containsNumericCharacter= */ false,
20707
+ /* containsNonAlphanumericCharacter= */ false);
20708
+ let passwordChar;
20709
+ for (let i = 0; i < password.length; i++) {
20710
+ passwordChar = password.charAt(i);
20711
+ this.updatePasswordCharacterOptionsStatuses(status,
20712
+ /* containsLowercaseCharacter= */ passwordChar >= 'a' &&
20713
+ passwordChar <= 'z',
20714
+ /* containsUppercaseCharacter= */ passwordChar >= 'A' &&
20715
+ passwordChar <= 'Z',
20716
+ /* containsNumericCharacter= */ passwordChar >= '0' &&
20717
+ passwordChar <= '9',
20718
+ /* containsNonAlphanumericCharacter= */ this.allowedNonAlphanumericCharacters.includes(passwordChar));
20425
20719
  }
20426
- function retrieveRecaptchaToken(siteKey, resolve, reject) {
20427
- const grecaptcha = window.grecaptcha;
20428
- if (isEnterprise(grecaptcha)) {
20429
- grecaptcha.enterprise.ready(() => {
20430
- grecaptcha.enterprise
20431
- .execute(siteKey, { action })
20432
- .then(token => {
20433
- resolve(token);
20434
- })
20435
- .catch(() => {
20436
- resolve(FAKE_TOKEN);
20437
- });
20438
- });
20439
- }
20440
- else {
20441
- reject(Error('No reCAPTCHA enterprise script loaded.'));
20442
- }
20443
- }
20444
- return new Promise((resolve, reject) => {
20445
- retrieveSiteKey(this.auth)
20446
- .then(siteKey => {
20447
- if (!forceRefresh && isEnterprise(window.grecaptcha)) {
20448
- retrieveRecaptchaToken(siteKey, resolve, reject);
20449
- }
20450
- else {
20451
- if (typeof window === 'undefined') {
20452
- reject(new Error('RecaptchaVerifier is only supported in browser'));
20453
- return;
20454
- }
20455
- _loadJS(RECAPTCHA_ENTERPRISE_URL + siteKey)
20456
- .then(() => {
20457
- retrieveRecaptchaToken(siteKey, resolve, reject);
20458
- })
20459
- .catch(error => {
20460
- reject(error);
20461
- });
20462
- }
20463
- })
20464
- .catch(error => {
20465
- reject(error);
20466
- });
20467
- });
20468
- }
20469
- }
20470
- async function injectRecaptchaFields(auth, request, action, captchaResp = false) {
20471
- const verifier = new RecaptchaEnterpriseVerifier(auth);
20472
- let captchaResponse;
20473
- try {
20474
- captchaResponse = await verifier.verify(action);
20475
- }
20476
- catch (error) {
20477
- captchaResponse = await verifier.verify(action, true);
20478
- }
20479
- const newRequest = Object.assign({}, request);
20480
- if (!captchaResp) {
20481
- Object.assign(newRequest, { captchaResponse });
20482
- }
20483
- else {
20484
- Object.assign(newRequest, { 'captchaResp': captchaResponse });
20485
- }
20486
- Object.assign(newRequest, { 'clientType': "CLIENT_TYPE_WEB" /* RecaptchaClientType.WEB */ });
20487
- Object.assign(newRequest, {
20488
- 'recaptchaVersion': "RECAPTCHA_ENTERPRISE" /* RecaptchaVersion.ENTERPRISE */
20489
- });
20490
- return newRequest;
20491
- }
20492
-
20493
- /**
20494
- * @license
20495
- * Copyright 2022 Google LLC
20496
- *
20497
- * Licensed under the Apache License, Version 2.0 (the "License");
20498
- * you may not use this file except in compliance with the License.
20499
- * You may obtain a copy of the License at
20500
- *
20501
- * http://www.apache.org/licenses/LICENSE-2.0
20502
- *
20503
- * Unless required by applicable law or agreed to in writing, software
20504
- * distributed under the License is distributed on an "AS IS" BASIS,
20505
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20506
- * See the License for the specific language governing permissions and
20507
- * limitations under the License.
20508
- */
20509
- class AuthMiddlewareQueue {
20510
- constructor(auth) {
20511
- this.auth = auth;
20512
- this.queue = [];
20513
20720
  }
20514
- pushCallback(callback, onAbort) {
20515
- // The callback could be sync or async. Wrap it into a
20516
- // function that is always async.
20517
- const wrappedCallback = (user) => new Promise((resolve, reject) => {
20518
- try {
20519
- const result = callback(user);
20520
- // Either resolve with existing promise or wrap a non-promise
20521
- // return value into a promise.
20522
- resolve(result);
20523
- }
20524
- catch (e) {
20525
- // Sync callback throws.
20526
- reject(e);
20527
- }
20528
- });
20529
- // Attach the onAbort if present
20530
- wrappedCallback.onAbort = onAbort;
20531
- this.queue.push(wrappedCallback);
20532
- const index = this.queue.length - 1;
20533
- return () => {
20534
- // Unsubscribe. Replace with no-op. Do not remove from array, or it will disturb
20535
- // indexing of other elements.
20536
- this.queue[index] = () => Promise.resolve();
20537
- };
20538
- }
20539
- async runMiddleware(nextUser) {
20540
- if (this.auth.currentUser === nextUser) {
20541
- return;
20721
+ /**
20722
+ * Updates the running validation status with the statuses for the character options.
20723
+ * Expected to be called each time a character is processed to update each option status
20724
+ * based on the current character.
20725
+ *
20726
+ * @param status Validation status.
20727
+ * @param containsLowercaseCharacter Whether the character is a lowercase letter.
20728
+ * @param containsUppercaseCharacter Whether the character is an uppercase letter.
20729
+ * @param containsNumericCharacter Whether the character is a numeric character.
20730
+ * @param containsNonAlphanumericCharacter Whether the character is a non-alphanumeric character.
20731
+ */
20732
+ updatePasswordCharacterOptionsStatuses(status, containsLowercaseCharacter, containsUppercaseCharacter, containsNumericCharacter, containsNonAlphanumericCharacter) {
20733
+ if (this.customStrengthOptions.containsLowercaseLetter) {
20734
+ status.containsLowercaseLetter || (status.containsLowercaseLetter = containsLowercaseCharacter);
20542
20735
  }
20543
- // While running the middleware, build a temporary stack of onAbort
20544
- // callbacks to call if one middleware callback rejects.
20545
- const onAbortStack = [];
20546
- try {
20547
- for (const beforeStateCallback of this.queue) {
20548
- await beforeStateCallback(nextUser);
20549
- // Only push the onAbort if the callback succeeds
20550
- if (beforeStateCallback.onAbort) {
20551
- onAbortStack.push(beforeStateCallback.onAbort);
20552
- }
20553
- }
20736
+ if (this.customStrengthOptions.containsUppercaseLetter) {
20737
+ status.containsUppercaseLetter || (status.containsUppercaseLetter = containsUppercaseCharacter);
20554
20738
  }
20555
- catch (e) {
20556
- // Run all onAbort, with separate try/catch to ignore any errors and
20557
- // continue
20558
- onAbortStack.reverse();
20559
- for (const onAbort of onAbortStack) {
20560
- try {
20561
- onAbort();
20562
- }
20563
- catch (_) {
20564
- /* swallow error */
20565
- }
20566
- }
20567
- throw this.auth._errorFactory.create("login-blocked" /* AuthErrorCode.LOGIN_BLOCKED */, {
20568
- originalMessage: e === null || e === void 0 ? void 0 : e.message
20569
- });
20739
+ if (this.customStrengthOptions.containsNumericCharacter) {
20740
+ status.containsNumericCharacter || (status.containsNumericCharacter = containsNumericCharacter);
20741
+ }
20742
+ if (this.customStrengthOptions.containsNonAlphanumericCharacter) {
20743
+ status.containsNonAlphanumericCharacter || (status.containsNonAlphanumericCharacter = containsNonAlphanumericCharacter);
20570
20744
  }
20571
20745
  }
20572
20746
  }
@@ -20601,6 +20775,7 @@ class AuthImpl {
20601
20775
  this.beforeStateQueue = new AuthMiddlewareQueue(this);
20602
20776
  this.redirectUser = null;
20603
20777
  this.isProactiveRefreshEnabled = false;
20778
+ this.EXPECTED_PASSWORD_POLICY_SCHEMA_VERSION = 1;
20604
20779
  // Any network calls will set this to true and prevent subsequent emulator
20605
20780
  // initialization
20606
20781
  this._canInitEmulator = true;
@@ -20611,6 +20786,8 @@ class AuthImpl {
20611
20786
  this._errorFactory = _DEFAULT_AUTH_ERROR_FACTORY;
20612
20787
  this._agentRecaptchaConfig = null;
20613
20788
  this._tenantRecaptchaConfigs = {};
20789
+ this._projectPasswordPolicy = null;
20790
+ this._tenantPasswordPolicies = {};
20614
20791
  // Tracks the last notified UID for state change listeners to prevent
20615
20792
  // repeated calls to the callbacks. Undefined means it's never been
20616
20793
  // called, whereas null means it's been called with a signed out user
@@ -20682,8 +20859,32 @@ class AuthImpl {
20682
20859
  // Skip blocking callbacks, they should not apply to a change in another tab.
20683
20860
  await this._updateCurrentUser(user, /* skipBeforeStateCallbacks */ true);
20684
20861
  }
20862
+ async initializeCurrentUserFromIdToken(idToken) {
20863
+ try {
20864
+ const response = await getAccountInfo(this, { idToken });
20865
+ const user = await UserImpl._fromGetAccountInfoResponse(this, response, idToken);
20866
+ await this.directlySetCurrentUser(user);
20867
+ }
20868
+ catch (err) {
20869
+ console.warn('FirebaseServerApp could not login user with provided authIdToken: ', err);
20870
+ await this.directlySetCurrentUser(null);
20871
+ }
20872
+ }
20685
20873
  async initializeCurrentUser(popupRedirectResolver) {
20686
20874
  var _a;
20875
+ if (_isFirebaseServerApp(this.app)) {
20876
+ const idToken = this.app.settings.authIdToken;
20877
+ if (idToken) {
20878
+ // Start the auth operation in the next tick to allow a moment for the customer's app to
20879
+ // attach an emulator, if desired.
20880
+ return new Promise(resolve => {
20881
+ setTimeout(() => this.initializeCurrentUserFromIdToken(idToken).then(resolve, resolve));
20882
+ });
20883
+ }
20884
+ else {
20885
+ return this.directlySetCurrentUser(null);
20886
+ }
20887
+ }
20687
20888
  // First check to see if we have a pending redirect event.
20688
20889
  const previouslyStoredUser = (await this.assertedPersistence.getCurrentUser());
20689
20890
  let futureCurrentUser = previouslyStoredUser;
@@ -20789,6 +20990,9 @@ class AuthImpl {
20789
20990
  this._deleted = true;
20790
20991
  }
20791
20992
  async updateCurrentUser(userExtern) {
20993
+ if (_isFirebaseServerApp(this.app)) {
20994
+ return Promise.reject(_serverAppCurrentUserOperationNotSupportedError(this));
20995
+ }
20792
20996
  // The public updateCurrentUser method needs to make a copy of the user,
20793
20997
  // and also check that the project matches
20794
20998
  const user = userExtern
@@ -20815,6 +21019,9 @@ class AuthImpl {
20815
21019
  });
20816
21020
  }
20817
21021
  async signOut() {
21022
+ if (_isFirebaseServerApp(this.app)) {
21023
+ return Promise.reject(_serverAppCurrentUserOperationNotSupportedError(this));
21024
+ }
20818
21025
  // Run first, to block _setRedirectUser() if any callbacks fail.
20819
21026
  await this.beforeStateQueue.runMiddleware(null);
20820
21027
  // Clear the redirect user when signOut is called
@@ -20826,33 +21033,51 @@ class AuthImpl {
20826
21033
  return this._updateCurrentUser(null, /* skipBeforeStateCallbacks */ true);
20827
21034
  }
20828
21035
  setPersistence(persistence) {
21036
+ if (_isFirebaseServerApp(this.app)) {
21037
+ return Promise.reject(_serverAppCurrentUserOperationNotSupportedError(this));
21038
+ }
20829
21039
  return this.queue(async () => {
20830
21040
  await this.assertedPersistence.setPersistence(_getInstance(persistence));
20831
21041
  });
20832
21042
  }
20833
- async initializeRecaptchaConfig() {
20834
- const response = await getRecaptchaConfig(this, {
20835
- clientType: "CLIENT_TYPE_WEB" /* RecaptchaClientType.WEB */,
20836
- version: "RECAPTCHA_ENTERPRISE" /* RecaptchaVersion.ENTERPRISE */
20837
- });
20838
- const config = new RecaptchaConfig(response);
21043
+ _getRecaptchaConfig() {
20839
21044
  if (this.tenantId == null) {
20840
- this._agentRecaptchaConfig = config;
21045
+ return this._agentRecaptchaConfig;
20841
21046
  }
20842
21047
  else {
20843
- this._tenantRecaptchaConfigs[this.tenantId] = config;
21048
+ return this._tenantRecaptchaConfigs[this.tenantId];
21049
+ }
21050
+ }
21051
+ async validatePassword(password) {
21052
+ if (!this._getPasswordPolicyInternal()) {
21053
+ await this._updatePasswordPolicy();
20844
21054
  }
20845
- if (config.emailPasswordEnabled) {
20846
- const verifier = new RecaptchaEnterpriseVerifier(this);
20847
- void verifier.verify();
21055
+ // Password policy will be defined after fetching.
21056
+ const passwordPolicy = this._getPasswordPolicyInternal();
21057
+ // Check that the policy schema version is supported by the SDK.
21058
+ // TODO: Update this logic to use a max supported policy schema version once we have multiple schema versions.
21059
+ if (passwordPolicy.schemaVersion !==
21060
+ this.EXPECTED_PASSWORD_POLICY_SCHEMA_VERSION) {
21061
+ return Promise.reject(this._errorFactory.create("unsupported-password-policy-schema-version" /* AuthErrorCode.UNSUPPORTED_PASSWORD_POLICY_SCHEMA_VERSION */, {}));
20848
21062
  }
21063
+ return passwordPolicy.validatePassword(password);
20849
21064
  }
20850
- _getRecaptchaConfig() {
20851
- if (this.tenantId == null) {
20852
- return this._agentRecaptchaConfig;
21065
+ _getPasswordPolicyInternal() {
21066
+ if (this.tenantId === null) {
21067
+ return this._projectPasswordPolicy;
20853
21068
  }
20854
21069
  else {
20855
- return this._tenantRecaptchaConfigs[this.tenantId];
21070
+ return this._tenantPasswordPolicies[this.tenantId];
21071
+ }
21072
+ }
21073
+ async _updatePasswordPolicy() {
21074
+ const response = await _getPasswordPolicy(this);
21075
+ const passwordPolicy = new PasswordPolicyImpl(response);
21076
+ if (this.tenantId === null) {
21077
+ this._projectPasswordPolicy = passwordPolicy;
21078
+ }
21079
+ else {
21080
+ this._tenantPasswordPolicies[this.tenantId] = passwordPolicy;
20856
21081
  }
20857
21082
  }
20858
21083
  _getPersistence() {
@@ -20870,6 +21095,38 @@ class AuthImpl {
20870
21095
  onIdTokenChanged(nextOrObserver, error, completed) {
20871
21096
  return this.registerStateListener(this.idTokenSubscription, nextOrObserver, error, completed);
20872
21097
  }
21098
+ authStateReady() {
21099
+ return new Promise((resolve, reject) => {
21100
+ if (this.currentUser) {
21101
+ resolve();
21102
+ }
21103
+ else {
21104
+ const unsubscribe = this.onAuthStateChanged(() => {
21105
+ unsubscribe();
21106
+ resolve();
21107
+ }, reject);
21108
+ }
21109
+ });
21110
+ }
21111
+ /**
21112
+ * Revokes the given access token. Currently only supports Apple OAuth access tokens.
21113
+ */
21114
+ async revokeAccessToken(token) {
21115
+ if (this.currentUser) {
21116
+ const idToken = await this.currentUser.getIdToken();
21117
+ // Generalize this to accept other providers once supported.
21118
+ const request = {
21119
+ providerId: 'apple.com',
21120
+ tokenType: "ACCESS_TOKEN" /* TokenType.ACCESS_TOKEN */,
21121
+ token,
21122
+ idToken
21123
+ };
21124
+ if (this.tenantId != null) {
21125
+ request.tenantId = this.tenantId;
21126
+ }
21127
+ await revokeToken(this, request);
21128
+ }
21129
+ }
20873
21130
  toJSON() {
20874
21131
  var _a;
20875
21132
  return {
@@ -20960,18 +21217,32 @@ class AuthImpl {
20960
21217
  const cb = typeof nextOrObserver === 'function'
20961
21218
  ? nextOrObserver
20962
21219
  : nextOrObserver.next.bind(nextOrObserver);
21220
+ let isUnsubscribed = false;
20963
21221
  const promise = this._isInitialized
20964
21222
  ? Promise.resolve()
20965
21223
  : this._initializationPromise;
20966
21224
  _assert(promise, this, "internal-error" /* AuthErrorCode.INTERNAL_ERROR */);
20967
21225
  // The callback needs to be called asynchronously per the spec.
20968
21226
  // eslint-disable-next-line @typescript-eslint/no-floating-promises
20969
- promise.then(() => cb(this.currentUser));
21227
+ promise.then(() => {
21228
+ if (isUnsubscribed) {
21229
+ return;
21230
+ }
21231
+ cb(this.currentUser);
21232
+ });
20970
21233
  if (typeof nextOrObserver === 'function') {
20971
- return subscription.addObserver(nextOrObserver, error, completed);
21234
+ const unsubscribe = subscription.addObserver(nextOrObserver, error, completed);
21235
+ return () => {
21236
+ isUnsubscribed = true;
21237
+ unsubscribe();
21238
+ };
20972
21239
  }
20973
21240
  else {
20974
- return subscription.addObserver(nextOrObserver);
21241
+ const unsubscribe = subscription.addObserver(nextOrObserver);
21242
+ return () => {
21243
+ isUnsubscribed = true;
21244
+ unsubscribe();
21245
+ };
20975
21246
  }
20976
21247
  }
20977
21248
  /**
@@ -21056,7 +21327,7 @@ class AuthImpl {
21056
21327
  }
21057
21328
  }
21058
21329
  /**
21059
- * Method to be used to cast down to our private implmentation of Auth.
21330
+ * Method to be used to cast down to our private implementation of Auth.
21060
21331
  * It will also handle unwrapping from the compat type if necessary
21061
21332
  *
21062
21333
  * @param auth Auth object passed in from developer
@@ -21077,6 +21348,194 @@ class Subscription {
21077
21348
  }
21078
21349
  }
21079
21350
 
21351
+ /**
21352
+ * @license
21353
+ * Copyright 2020 Google LLC
21354
+ *
21355
+ * Licensed under the Apache License, Version 2.0 (the "License");
21356
+ * you may not use this file except in compliance with the License.
21357
+ * You may obtain a copy of the License at
21358
+ *
21359
+ * http://www.apache.org/licenses/LICENSE-2.0
21360
+ *
21361
+ * Unless required by applicable law or agreed to in writing, software
21362
+ * distributed under the License is distributed on an "AS IS" BASIS,
21363
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21364
+ * See the License for the specific language governing permissions and
21365
+ * limitations under the License.
21366
+ */
21367
+ let externalJSProvider = {
21368
+ async loadJS() {
21369
+ throw new Error('Unable to load external scripts');
21370
+ },
21371
+ recaptchaV2Script: '',
21372
+ recaptchaEnterpriseScript: '',
21373
+ gapiScript: ''
21374
+ };
21375
+ function _setExternalJSProvider(p) {
21376
+ externalJSProvider = p;
21377
+ }
21378
+ function _loadJS(url) {
21379
+ return externalJSProvider.loadJS(url);
21380
+ }
21381
+ function _recaptchaEnterpriseScriptUrl() {
21382
+ return externalJSProvider.recaptchaEnterpriseScript;
21383
+ }
21384
+ function _gapiScriptUrl() {
21385
+ return externalJSProvider.gapiScript;
21386
+ }
21387
+ function _generateCallbackName(prefix) {
21388
+ return `__${prefix}${Math.floor(Math.random() * 1000000)}`;
21389
+ }
21390
+
21391
+ /* eslint-disable @typescript-eslint/no-require-imports */
21392
+ const RECAPTCHA_ENTERPRISE_VERIFIER_TYPE = 'recaptcha-enterprise';
21393
+ const FAKE_TOKEN = 'NO_RECAPTCHA';
21394
+ class RecaptchaEnterpriseVerifier {
21395
+ /**
21396
+ *
21397
+ * @param authExtern - The corresponding Firebase {@link Auth} instance.
21398
+ *
21399
+ */
21400
+ constructor(authExtern) {
21401
+ /**
21402
+ * Identifies the type of application verifier (e.g. "recaptcha-enterprise").
21403
+ */
21404
+ this.type = RECAPTCHA_ENTERPRISE_VERIFIER_TYPE;
21405
+ this.auth = _castAuth(authExtern);
21406
+ }
21407
+ /**
21408
+ * Executes the verification process.
21409
+ *
21410
+ * @returns A Promise for a token that can be used to assert the validity of a request.
21411
+ */
21412
+ async verify(action = 'verify', forceRefresh = false) {
21413
+ async function retrieveSiteKey(auth) {
21414
+ if (!forceRefresh) {
21415
+ if (auth.tenantId == null && auth._agentRecaptchaConfig != null) {
21416
+ return auth._agentRecaptchaConfig.siteKey;
21417
+ }
21418
+ if (auth.tenantId != null &&
21419
+ auth._tenantRecaptchaConfigs[auth.tenantId] !== undefined) {
21420
+ return auth._tenantRecaptchaConfigs[auth.tenantId].siteKey;
21421
+ }
21422
+ }
21423
+ return new Promise(async (resolve, reject) => {
21424
+ getRecaptchaConfig(auth, {
21425
+ clientType: "CLIENT_TYPE_WEB" /* RecaptchaClientType.WEB */,
21426
+ version: "RECAPTCHA_ENTERPRISE" /* RecaptchaVersion.ENTERPRISE */
21427
+ })
21428
+ .then(response => {
21429
+ if (response.recaptchaKey === undefined) {
21430
+ reject(new Error('recaptcha Enterprise site key undefined'));
21431
+ }
21432
+ else {
21433
+ const config = new RecaptchaConfig(response);
21434
+ if (auth.tenantId == null) {
21435
+ auth._agentRecaptchaConfig = config;
21436
+ }
21437
+ else {
21438
+ auth._tenantRecaptchaConfigs[auth.tenantId] = config;
21439
+ }
21440
+ return resolve(config.siteKey);
21441
+ }
21442
+ })
21443
+ .catch(error => {
21444
+ reject(error);
21445
+ });
21446
+ });
21447
+ }
21448
+ function retrieveRecaptchaToken(siteKey, resolve, reject) {
21449
+ const grecaptcha = window.grecaptcha;
21450
+ if (isEnterprise(grecaptcha)) {
21451
+ grecaptcha.enterprise.ready(() => {
21452
+ grecaptcha.enterprise
21453
+ .execute(siteKey, { action })
21454
+ .then(token => {
21455
+ resolve(token);
21456
+ })
21457
+ .catch(() => {
21458
+ resolve(FAKE_TOKEN);
21459
+ });
21460
+ });
21461
+ }
21462
+ else {
21463
+ reject(Error('No reCAPTCHA enterprise script loaded.'));
21464
+ }
21465
+ }
21466
+ return new Promise((resolve, reject) => {
21467
+ retrieveSiteKey(this.auth)
21468
+ .then(siteKey => {
21469
+ if (!forceRefresh && isEnterprise(window.grecaptcha)) {
21470
+ retrieveRecaptchaToken(siteKey, resolve, reject);
21471
+ }
21472
+ else {
21473
+ if (typeof window === 'undefined') {
21474
+ reject(new Error('RecaptchaVerifier is only supported in browser'));
21475
+ return;
21476
+ }
21477
+ let url = _recaptchaEnterpriseScriptUrl();
21478
+ if (url.length !== 0) {
21479
+ url += siteKey;
21480
+ }
21481
+ _loadJS(url)
21482
+ .then(() => {
21483
+ retrieveRecaptchaToken(siteKey, resolve, reject);
21484
+ })
21485
+ .catch(error => {
21486
+ reject(error);
21487
+ });
21488
+ }
21489
+ })
21490
+ .catch(error => {
21491
+ reject(error);
21492
+ });
21493
+ });
21494
+ }
21495
+ }
21496
+ async function injectRecaptchaFields(auth, request, action, captchaResp = false) {
21497
+ const verifier = new RecaptchaEnterpriseVerifier(auth);
21498
+ let captchaResponse;
21499
+ try {
21500
+ captchaResponse = await verifier.verify(action);
21501
+ }
21502
+ catch (error) {
21503
+ captchaResponse = await verifier.verify(action, true);
21504
+ }
21505
+ const newRequest = Object.assign({}, request);
21506
+ if (!captchaResp) {
21507
+ Object.assign(newRequest, { captchaResponse });
21508
+ }
21509
+ else {
21510
+ Object.assign(newRequest, { 'captchaResp': captchaResponse });
21511
+ }
21512
+ Object.assign(newRequest, { 'clientType': "CLIENT_TYPE_WEB" /* RecaptchaClientType.WEB */ });
21513
+ Object.assign(newRequest, {
21514
+ 'recaptchaVersion': "RECAPTCHA_ENTERPRISE" /* RecaptchaVersion.ENTERPRISE */
21515
+ });
21516
+ return newRequest;
21517
+ }
21518
+ async function handleRecaptchaFlow(authInstance, request, actionName, actionMethod) {
21519
+ var _a;
21520
+ if ((_a = authInstance
21521
+ ._getRecaptchaConfig()) === null || _a === void 0 ? void 0 : _a.isProviderEnabled("EMAIL_PASSWORD_PROVIDER" /* RecaptchaProvider.EMAIL_PASSWORD_PROVIDER */)) {
21522
+ const requestWithRecaptcha = await injectRecaptchaFields(authInstance, request, actionName, actionName === "getOobCode" /* RecaptchaActionName.GET_OOB_CODE */);
21523
+ return actionMethod(authInstance, requestWithRecaptcha);
21524
+ }
21525
+ else {
21526
+ return actionMethod(authInstance, request).catch(async (error) => {
21527
+ if (error.code === `auth/${"missing-recaptcha-token" /* AuthErrorCode.MISSING_RECAPTCHA_TOKEN */}`) {
21528
+ console.log(`${actionName} is protected by reCAPTCHA Enterprise for this project. Automatically triggering the reCAPTCHA flow and restarting the flow.`);
21529
+ const requestWithRecaptcha = await injectRecaptchaFields(authInstance, request, actionName, actionName === "getOobCode" /* RecaptchaActionName.GET_OOB_CODE */);
21530
+ return actionMethod(authInstance, requestWithRecaptcha);
21531
+ }
21532
+ else {
21533
+ return Promise.reject(error);
21534
+ }
21535
+ });
21536
+ }
21537
+ }
21538
+
21080
21539
  /**
21081
21540
  * @license
21082
21541
  * Copyright 2020 Google LLC
@@ -21340,8 +21799,10 @@ class AuthCredential {
21340
21799
  async function resetPassword(auth, request) {
21341
21800
  return _performApiRequest(auth, "POST" /* HttpMethod.POST */, "/v1/accounts:resetPassword" /* Endpoint.RESET_PASSWORD */, _addTidIfNecessary(auth, request));
21342
21801
  }
21343
- async function updateEmailPassword(auth, request) {
21344
- return _performApiRequest(auth, "POST" /* HttpMethod.POST */, "/v1/accounts:update" /* Endpoint.SET_ACCOUNT_INFO */, request);
21802
+ // Used for linking an email/password account to an existing idToken. Uses the same request/response
21803
+ // format as updateEmailPassword.
21804
+ async function linkEmailPassword(auth, request) {
21805
+ return _performApiRequest(auth, "POST" /* HttpMethod.POST */, "/v1/accounts:signUp" /* Endpoint.SIGN_UP */, request);
21345
21806
  }
21346
21807
 
21347
21808
  /**
@@ -21472,7 +21933,6 @@ class EmailAuthCredential extends AuthCredential {
21472
21933
  }
21473
21934
  /** @internal */
21474
21935
  async _getIdTokenResponse(auth) {
21475
- var _a;
21476
21936
  switch (this.signInMethod) {
21477
21937
  case "password" /* SignInMethod.EMAIL_PASSWORD */:
21478
21938
  const request = {
@@ -21481,22 +21941,7 @@ class EmailAuthCredential extends AuthCredential {
21481
21941
  password: this._password,
21482
21942
  clientType: "CLIENT_TYPE_WEB" /* RecaptchaClientType.WEB */
21483
21943
  };
21484
- if ((_a = auth._getRecaptchaConfig()) === null || _a === void 0 ? void 0 : _a.emailPasswordEnabled) {
21485
- const requestWithRecaptcha = await injectRecaptchaFields(auth, request, "signInWithPassword" /* RecaptchaActionName.SIGN_IN_WITH_PASSWORD */);
21486
- return signInWithPassword(auth, requestWithRecaptcha);
21487
- }
21488
- else {
21489
- return signInWithPassword(auth, request).catch(async (error) => {
21490
- if (error.code === `auth/${"missing-recaptcha-token" /* AuthErrorCode.MISSING_RECAPTCHA_TOKEN */}`) {
21491
- console.log('Sign-in with email address and password is protected by reCAPTCHA for this project. Automatically triggering the reCAPTCHA flow and restarting the sign-in flow.');
21492
- const requestWithRecaptcha = await injectRecaptchaFields(auth, request, "signInWithPassword" /* RecaptchaActionName.SIGN_IN_WITH_PASSWORD */);
21493
- return signInWithPassword(auth, requestWithRecaptcha);
21494
- }
21495
- else {
21496
- return Promise.reject(error);
21497
- }
21498
- });
21499
- }
21944
+ return handleRecaptchaFlow(auth, request, "signInWithPassword" /* RecaptchaActionName.SIGN_IN_WITH_PASSWORD */, signInWithPassword);
21500
21945
  case "emailLink" /* SignInMethod.EMAIL_LINK */:
21501
21946
  return signInWithEmailLink$1(auth, {
21502
21947
  email: this._email,
@@ -21510,12 +21955,14 @@ class EmailAuthCredential extends AuthCredential {
21510
21955
  async _linkToIdToken(auth, idToken) {
21511
21956
  switch (this.signInMethod) {
21512
21957
  case "password" /* SignInMethod.EMAIL_PASSWORD */:
21513
- return updateEmailPassword(auth, {
21958
+ const request = {
21514
21959
  idToken,
21515
21960
  returnSecureToken: true,
21516
21961
  email: this._email,
21517
- password: this._password
21518
- });
21962
+ password: this._password,
21963
+ clientType: "CLIENT_TYPE_WEB" /* RecaptchaClientType.WEB */
21964
+ };
21965
+ return handleRecaptchaFlow(auth, request, "signUpPassword" /* RecaptchaActionName.SIGN_UP_PASSWORD */, linkEmailPassword);
21519
21966
  case "emailLink" /* SignInMethod.EMAIL_LINK */:
21520
21967
  return signInWithEmailLinkForLinking(auth, {
21521
21968
  idToken,
@@ -22133,7 +22580,7 @@ FacebookAuthProvider.PROVIDER_ID = "facebook.com" /* ProviderId.FACEBOOK */;
22133
22580
  * limitations under the License.
22134
22581
  */
22135
22582
  /**
22136
- * Provider for generating an an {@link OAuthCredential} for {@link ProviderId}.GOOGLE.
22583
+ * Provider for generating an {@link OAuthCredential} for {@link ProviderId}.GOOGLE.
22137
22584
  *
22138
22585
  * @example
22139
22586
  * ```javascript
@@ -22275,7 +22722,7 @@ GoogleAuthProvider.PROVIDER_ID = "google.com" /* ProviderId.GOOGLE */;
22275
22722
  * if (result) {
22276
22723
  * // This is the signed-in user
22277
22724
  * const user = result.user;
22278
- * // This gives you a Github Access Token.
22725
+ * // This gives you a GitHub Access Token.
22279
22726
  * const credential = GithubAuthProvider.credentialFromResult(result);
22280
22727
  * const token = credential.accessToken;
22281
22728
  * }
@@ -22290,7 +22737,7 @@ GoogleAuthProvider.PROVIDER_ID = "google.com" /* ProviderId.GOOGLE */;
22290
22737
  *
22291
22738
  * // The signed-in user info.
22292
22739
  * const user = result.user;
22293
- * // This gives you a Github Access Token.
22740
+ * // This gives you a GitHub Access Token.
22294
22741
  * const credential = GithubAuthProvider.credentialFromResult(result);
22295
22742
  * const token = credential.accessToken;
22296
22743
  * ```
@@ -22301,9 +22748,9 @@ class GithubAuthProvider extends BaseOAuthProvider {
22301
22748
  super("github.com" /* ProviderId.GITHUB */);
22302
22749
  }
22303
22750
  /**
22304
- * Creates a credential for Github.
22751
+ * Creates a credential for GitHub.
22305
22752
  *
22306
- * @param accessToken - Github access token.
22753
+ * @param accessToken - GitHub access token.
22307
22754
  */
22308
22755
  static credential(accessToken) {
22309
22756
  return OAuthCredential._fromParams({
@@ -22584,6 +23031,9 @@ async function _link$1(user, credential, bypassAuthState = false) {
22584
23031
  */
22585
23032
  async function _reauthenticate(user, credential, bypassAuthState = false) {
22586
23033
  const { auth } = user;
23034
+ if (_isFirebaseServerApp(auth.app)) {
23035
+ return Promise.reject(_serverAppCurrentUserOperationNotSupportedError(auth));
23036
+ }
22587
23037
  const operationType = "reauthenticate" /* OperationType.REAUTHENTICATE */;
22588
23038
  try {
22589
23039
  const response = await _logoutIfInvalidated(user, _processCredentialSavingMfaContextIfNecessary(auth, operationType, credential, user), bypassAuthState);
@@ -22620,6 +23070,9 @@ async function _reauthenticate(user, credential, bypassAuthState = false) {
22620
23070
  * limitations under the License.
22621
23071
  */
22622
23072
  async function _signInWithCredential(auth, credential, bypassAuthState = false) {
23073
+ if (_isFirebaseServerApp(auth.app)) {
23074
+ return Promise.reject(_serverAppCurrentUserOperationNotSupportedError(auth));
23075
+ }
22623
23076
  const operationType = "signIn" /* OperationType.SIGN_IN */;
22624
23077
  const response = await _processCredentialSavingMfaContextIfNecessary(auth, operationType, credential);
22625
23078
  const userCredential = await UserCredentialImpl._fromIdTokenResponse(auth, operationType, response);
@@ -22634,6 +23087,9 @@ async function _signInWithCredential(auth, credential, bypassAuthState = false)
22634
23087
  * @remarks
22635
23088
  * An {@link AuthProvider} can be used to generate the credential.
22636
23089
  *
23090
+ * This method is not supported by {@link Auth} instances created with a
23091
+ * {@link @firebase/app#FirebaseServerApp}.
23092
+ *
22637
23093
  * @param auth - The {@link Auth} instance.
22638
23094
  * @param credential - The auth credential.
22639
23095
  *
@@ -22697,7 +23153,29 @@ function _setActionCodeSettingsOnRequest(auth, request, actionCodeSettings) {
22697
23153
  * limitations under the License.
22698
23154
  */
22699
23155
  /**
22700
- * Sends a password reset email to the given email address.
23156
+ * Updates the password policy cached in the {@link Auth} instance if a policy is already
23157
+ * cached for the project or tenant.
23158
+ *
23159
+ * @remarks
23160
+ * We only fetch the password policy if the password did not meet policy requirements and
23161
+ * there is an existing policy cached. A developer must call validatePassword at least
23162
+ * once for the cache to be automatically updated.
23163
+ *
23164
+ * @param auth - The {@link Auth} instance.
23165
+ *
23166
+ * @private
23167
+ */
23168
+ async function recachePasswordPolicy(auth) {
23169
+ const authInternal = _castAuth(auth);
23170
+ if (authInternal._getPasswordPolicyInternal()) {
23171
+ await authInternal._updatePasswordPolicy();
23172
+ }
23173
+ }
23174
+ /**
23175
+ * Sends a password reset email to the given email address. This method does not throw an error when
23176
+ * there's no user account with the given email address and
23177
+ * {@link https://cloud.google.com/identity-platform/docs/admin/email-enumeration-protection | Email Enumeration Protection}
23178
+ * is enabled.
22701
23179
  *
22702
23180
  * @remarks
22703
23181
  * To complete the password reset, call {@link confirmPasswordReset} with the code supplied in
@@ -22729,39 +23207,16 @@ function _setActionCodeSettingsOnRequest(auth, request, actionCodeSettings) {
22729
23207
  * @public
22730
23208
  */
22731
23209
  async function sendPasswordResetEmail(auth, email, actionCodeSettings) {
22732
- var _a;
22733
23210
  const authInternal = _castAuth(auth);
22734
23211
  const request = {
22735
23212
  requestType: "PASSWORD_RESET" /* ActionCodeOperation.PASSWORD_RESET */,
22736
23213
  email,
22737
23214
  clientType: "CLIENT_TYPE_WEB" /* RecaptchaClientType.WEB */
22738
23215
  };
22739
- if ((_a = authInternal._getRecaptchaConfig()) === null || _a === void 0 ? void 0 : _a.emailPasswordEnabled) {
22740
- const requestWithRecaptcha = await injectRecaptchaFields(authInternal, request, "getOobCode" /* RecaptchaActionName.GET_OOB_CODE */, true);
22741
- if (actionCodeSettings) {
22742
- _setActionCodeSettingsOnRequest(authInternal, requestWithRecaptcha, actionCodeSettings);
22743
- }
22744
- await sendPasswordResetEmail$1(authInternal, requestWithRecaptcha);
22745
- }
22746
- else {
22747
- if (actionCodeSettings) {
22748
- _setActionCodeSettingsOnRequest(authInternal, request, actionCodeSettings);
22749
- }
22750
- await sendPasswordResetEmail$1(authInternal, request)
22751
- .catch(async (error) => {
22752
- if (error.code === `auth/${"missing-recaptcha-token" /* AuthErrorCode.MISSING_RECAPTCHA_TOKEN */}`) {
22753
- console.log('Password resets are protected by reCAPTCHA for this project. Automatically triggering the reCAPTCHA flow and restarting the password reset flow.');
22754
- const requestWithRecaptcha = await injectRecaptchaFields(authInternal, request, "getOobCode" /* RecaptchaActionName.GET_OOB_CODE */, true);
22755
- if (actionCodeSettings) {
22756
- _setActionCodeSettingsOnRequest(authInternal, requestWithRecaptcha, actionCodeSettings);
22757
- }
22758
- await sendPasswordResetEmail$1(authInternal, requestWithRecaptcha);
22759
- }
22760
- else {
22761
- return Promise.reject(error);
22762
- }
22763
- });
23216
+ if (actionCodeSettings) {
23217
+ _setActionCodeSettingsOnRequest(authInternal, request, actionCodeSettings);
22764
23218
  }
23219
+ await handleRecaptchaFlow(authInternal, request, "getOobCode" /* RecaptchaActionName.GET_OOB_CODE */, sendPasswordResetEmail$1);
22765
23220
  }
22766
23221
  /**
22767
23222
  * Completes the password reset process, given a confirmation code and new password.
@@ -22776,6 +23231,13 @@ async function confirmPasswordReset(auth, oobCode, newPassword) {
22776
23231
  await resetPassword(getModularInstance$1(auth), {
22777
23232
  oobCode,
22778
23233
  newPassword
23234
+ })
23235
+ .catch(async (error) => {
23236
+ if (error.code ===
23237
+ `auth/${"password-does-not-meet-requirements" /* AuthErrorCode.PASSWORD_DOES_NOT_MEET_REQUIREMENTS */}`) {
23238
+ void recachePasswordPolicy(auth);
23239
+ }
23240
+ throw error;
22779
23241
  });
22780
23242
  // Do not return the email.
22781
23243
  }
@@ -22783,12 +23245,19 @@ async function confirmPasswordReset(auth, oobCode, newPassword) {
22783
23245
  * Asynchronously signs in using an email and password.
22784
23246
  *
22785
23247
  * @remarks
22786
- * Fails with an error if the email address and password do not match.
23248
+ * Fails with an error if the email address and password do not match. When
23249
+ * {@link https://cloud.google.com/identity-platform/docs/admin/email-enumeration-protection | Email Enumeration Protection}
23250
+ * is enabled, this method fails with "auth/invalid-credential" in case of an invalid
23251
+ * email/password.
23252
+ *
23253
+ * This method is not supported on {@link Auth} instances created with a
23254
+ * {@link @firebase/app#FirebaseServerApp}.
22787
23255
  *
22788
23256
  * Note: The user's password is NOT the password used to access the user's email account. The
22789
23257
  * email address serves as a unique identifier for the user, and the password is used to access
22790
23258
  * the user's account in your Firebase project. See also: {@link createUserWithEmailAndPassword}.
22791
23259
  *
23260
+ *
22792
23261
  * @param auth - The {@link Auth} instance.
22793
23262
  * @param email - The users email address.
22794
23263
  * @param password - The users password.
@@ -22796,7 +23265,15 @@ async function confirmPasswordReset(auth, oobCode, newPassword) {
22796
23265
  * @public
22797
23266
  */
22798
23267
  function signInWithEmailAndPassword(auth, email, password) {
22799
- return signInWithCredential(getModularInstance$1(auth), EmailAuthProvider.credential(email, password));
23268
+ if (_isFirebaseServerApp(auth.app)) {
23269
+ return Promise.reject(_serverAppCurrentUserOperationNotSupportedError(auth));
23270
+ }
23271
+ return signInWithCredential(getModularInstance$1(auth), EmailAuthProvider.credential(email, password)).catch(async (error) => {
23272
+ if (error.code === `auth/${"password-does-not-meet-requirements" /* AuthErrorCode.PASSWORD_DOES_NOT_MEET_REQUIREMENTS */}`) {
23273
+ void recachePasswordPolicy(auth);
23274
+ }
23275
+ throw error;
23276
+ });
22800
23277
  }
22801
23278
  /**
22802
23279
  * Adds an observer for changes to the signed-in user's ID token.
@@ -22903,10 +23380,6 @@ class BrowserPersistenceClass {
22903
23380
  * See the License for the specific language governing permissions and
22904
23381
  * limitations under the License.
22905
23382
  */
22906
- function _iframeCannotSyncWebStorage() {
22907
- const ua = getUA();
22908
- return _isSafari(ua) || _isIOS(ua);
22909
- }
22910
23383
  // The polling period in case events are not supported
22911
23384
  const _POLLING_INTERVAL_MS$1 = 1000;
22912
23385
  // The IE 10 localStorage cross tab synchronization delay in milliseconds
@@ -22920,8 +23393,6 @@ class BrowserLocalPersistence extends BrowserPersistenceClass {
22920
23393
  // setTimeout return value is platform specific
22921
23394
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
22922
23395
  this.pollTimer = null;
22923
- // Safari or iOS browser and embedded in an iframe.
22924
- this.safariLocalStorageNotSynced = _iframeCannotSyncWebStorage() && _isIframe();
22925
23396
  // Whether to use polling instead of depending on window events
22926
23397
  this.fallbackToPolling = _isMobileBrowser();
22927
23398
  this._shouldAllowMigration = true;
@@ -22960,27 +23431,6 @@ class BrowserLocalPersistence extends BrowserPersistenceClass {
22960
23431
  // Remove polling listener to prevent possible event duplication.
22961
23432
  this.stopPolling();
22962
23433
  }
22963
- // Safari embedded iframe. Storage event will trigger with the delta
22964
- // changes but no changes will be applied to the iframe localStorage.
22965
- if (this.safariLocalStorageNotSynced) {
22966
- // Get current iframe page value.
22967
- const storedValue = this.storage.getItem(key);
22968
- // Value not synchronized, synchronize manually.
22969
- if (event.newValue !== storedValue) {
22970
- if (event.newValue !== null) {
22971
- // Value changed from current value.
22972
- this.storage.setItem(key, event.newValue);
22973
- }
22974
- else {
22975
- // Current value deleted.
22976
- this.storage.removeItem(key);
22977
- }
22978
- }
22979
- else if (this.localCache[key] === event.newValue && !poll) {
22980
- // Already detected and processed, do not trigger listeners again.
22981
- return;
22982
- }
22983
- }
22984
23434
  const triggerListeners = () => {
22985
23435
  // Keep local map up to date in case storage event is triggered before
22986
23436
  // poll.
@@ -23271,7 +23721,7 @@ class Receiver {
23271
23721
  * Unsubscribe an event handler from a particular event.
23272
23722
  *
23273
23723
  * @param eventType - Event name to unsubscribe from.
23274
- * @param eventHandler - Optinoal event handler, if none provided, unsubscribe all handlers on this event.
23724
+ * @param eventHandler - Optional event handler, if none provided, unsubscribe all handlers on this event.
23275
23725
  *
23276
23726
  */
23277
23727
  _unsubscribe(eventType, eventHandler) {
@@ -23765,11 +24215,13 @@ class IndexedDBLocalPersistence {
23765
24215
  }
23766
24216
  const keys = [];
23767
24217
  const keysInResult = new Set();
23768
- for (const { fbase_key: key, value } of result) {
23769
- keysInResult.add(key);
23770
- if (JSON.stringify(this.localCache[key]) !== JSON.stringify(value)) {
23771
- this.notifyListeners(key, value);
23772
- keys.push(key);
24218
+ if (result.length !== 0) {
24219
+ for (const { fbase_key: key, value } of result) {
24220
+ keysInResult.add(key);
24221
+ if (JSON.stringify(this.localCache[key]) !== JSON.stringify(value)) {
24222
+ this.notifyListeners(key, value);
24223
+ keys.push(key);
24224
+ }
23773
24225
  }
23774
24226
  }
23775
24227
  for (const localKey of Object.keys(this.localCache)) {
@@ -24225,6 +24677,9 @@ function pendingRedirectKey(auth) {
24225
24677
  return _persistenceKeyName(PENDING_REDIRECT_KEY, auth.config.apiKey, auth.name);
24226
24678
  }
24227
24679
  async function _getRedirectResult(auth, resolverExtern, bypassAuthState = false) {
24680
+ if (_isFirebaseServerApp(auth.app)) {
24681
+ return Promise.reject(_serverAppCurrentUserOperationNotSupportedError(auth));
24682
+ }
24228
24683
  const authInternal = _castAuth(auth);
24229
24684
  const resolver = _withDefaultResolver(authInternal, resolverExtern);
24230
24685
  const action = new RedirectAction(authInternal, resolver, bypassAuthState);
@@ -24455,7 +24910,7 @@ function matchDomain(expected) {
24455
24910
  */
24456
24911
  const NETWORK_TIMEOUT = new Delay(30000, 60000);
24457
24912
  /**
24458
- * Reset unlaoded GApi modules. If gapi.load fails due to a network error,
24913
+ * Reset unloaded GApi modules. If gapi.load fails due to a network error,
24459
24914
  * it will stop working after a retrial. This is a hack to fix this issue.
24460
24915
  */
24461
24916
  function resetUnloadedGapiModules() {
@@ -24535,7 +24990,7 @@ function loadGapi(auth) {
24535
24990
  }
24536
24991
  };
24537
24992
  // Load GApi loader.
24538
- return _loadJS(`https://apis.google.com/js/api.js?onload=${cbName}`)
24993
+ return _loadJS(`${_gapiScriptUrl()}?onload=${cbName}`)
24539
24994
  .catch(e => reject(e));
24540
24995
  }
24541
24996
  }).catch(error => {
@@ -24790,7 +25245,7 @@ async function _getRedirectUrl(auth, provider, authType, redirectUrl, eventId, a
24790
25245
  if (auth.tenantId) {
24791
25246
  params.tid = auth.tenantId;
24792
25247
  }
24793
- // TODO: maybe set eid as endipointId
25248
+ // TODO: maybe set eid as endpointId
24794
25249
  // TODO: maybe set fw as Frameworks.join(",")
24795
25250
  const paramsDict = params;
24796
25251
  for (const key of Object.keys(paramsDict)) {
@@ -24918,12 +25373,15 @@ class BrowserPopupRedirectResolver {
24918
25373
  * An implementation of {@link PopupRedirectResolver} suitable for browser
24919
25374
  * based applications.
24920
25375
  *
25376
+ * @remarks
25377
+ * This method does not work in a Node.js environment.
25378
+ *
24921
25379
  * @public
24922
25380
  */
24923
25381
  const browserPopupRedirectResolver = BrowserPopupRedirectResolver;
24924
25382
 
24925
25383
  var name = "@firebase/auth";
24926
- var version = "0.23.2";
25384
+ var version = "1.7.7";
24927
25385
 
24928
25386
  /**
24929
25387
  * @license
@@ -25020,6 +25478,8 @@ function getVersionForPlatform(clientPlatform) {
25020
25478
  return 'webworker';
25021
25479
  case "Cordova" /* ClientPlatform.CORDOVA */:
25022
25480
  return 'cordova';
25481
+ case "WebExtension" /* ClientPlatform.WEB_EXTENSION */:
25482
+ return 'web-extension';
25023
25483
  default:
25024
25484
  return undefined;
25025
25485
  }
@@ -25129,11 +25589,18 @@ function getAuth(app = getApp()) {
25129
25589
  browserSessionPersistence
25130
25590
  ]
25131
25591
  });
25132
- const authTokenSyncUrl = getExperimentalSetting('authTokenSyncURL');
25133
- if (authTokenSyncUrl) {
25134
- const mintCookie = mintCookieFactory(authTokenSyncUrl);
25135
- beforeAuthStateChanged(auth, mintCookie, () => mintCookie(auth.currentUser));
25136
- onIdTokenChanged(auth, user => mintCookie(user));
25592
+ const authTokenSyncPath = getExperimentalSetting('authTokenSyncURL');
25593
+ // Only do the Cookie exchange in a secure context
25594
+ if (authTokenSyncPath &&
25595
+ typeof isSecureContext === 'boolean' &&
25596
+ isSecureContext) {
25597
+ // Don't allow urls (XSS possibility), only paths on the same domain
25598
+ const authTokenSyncUrl = new URL(authTokenSyncPath, location.origin);
25599
+ if (location.origin === authTokenSyncUrl.origin) {
25600
+ const mintCookie = mintCookieFactory(authTokenSyncUrl.toString());
25601
+ beforeAuthStateChanged(auth, mintCookie, () => mintCookie(auth.currentUser));
25602
+ onIdTokenChanged(auth, user => mintCookie(user));
25603
+ }
25137
25604
  }
25138
25605
  const authEmulatorHost = getDefaultEmulatorHost$1('auth');
25139
25606
  if (authEmulatorHost) {
@@ -25141,6 +25608,31 @@ function getAuth(app = getApp()) {
25141
25608
  }
25142
25609
  return auth;
25143
25610
  }
25611
+ function getScriptParentElement() {
25612
+ var _a, _b;
25613
+ return (_b = (_a = document.getElementsByTagName('head')) === null || _a === void 0 ? void 0 : _a[0]) !== null && _b !== void 0 ? _b : document;
25614
+ }
25615
+ _setExternalJSProvider({
25616
+ loadJS(url) {
25617
+ // TODO: consider adding timeout support & cancellation
25618
+ return new Promise((resolve, reject) => {
25619
+ const el = document.createElement('script');
25620
+ el.setAttribute('src', url);
25621
+ el.onload = resolve;
25622
+ el.onerror = e => {
25623
+ const error = _createError("internal-error" /* AuthErrorCode.INTERNAL_ERROR */);
25624
+ error.customData = e;
25625
+ reject(error);
25626
+ };
25627
+ el.type = 'text/javascript';
25628
+ el.charset = 'UTF-8';
25629
+ getScriptParentElement().appendChild(el);
25630
+ });
25631
+ },
25632
+ gapiScript: 'https://apis.google.com/js/api.js',
25633
+ recaptchaV2Script: 'https://www.google.com/recaptcha/api.js',
25634
+ recaptchaEnterpriseScript: 'https://www.google.com/recaptcha/enterprise.js?render='
25635
+ });
25144
25636
  registerAuth("Browser" /* ClientPlatform.BROWSER */);
25145
25637
 
25146
25638
  const fromFirebaseDate = (date) => {
@@ -25187,16 +25679,16 @@ class FirebaseUser {
25187
25679
  var _a;
25188
25680
  return (_a = this.user) === null || _a === void 0 ? void 0 : _a.uid;
25189
25681
  }
25190
- onInit(brandId) {
25191
- return new Promise((resolve) => {
25192
- const unsub = this.auth.onAuthStateChanged((user) => {
25193
- this.setUser(user);
25194
- resolve(Boolean(user));
25195
- unsub();
25196
- if (user)
25197
- this.logUserLogin(brandId, user);
25198
- });
25682
+ async onInit(brandId) {
25683
+ this.auth.onAuthStateChanged((user) => {
25684
+ this.setUser(user);
25685
+ if (user)
25686
+ this.logUserLogin(brandId, user);
25199
25687
  });
25688
+ await this.auth.authStateReady();
25689
+ const user = this.auth.currentUser;
25690
+ this.setUser(user);
25691
+ return Boolean(user);
25200
25692
  }
25201
25693
  setUser(user) {
25202
25694
  this.user = user;