From 939a2e75af9ca25c31320f29a6ad1bd3040cc621 Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Mon, 19 May 2025 16:39:10 -0700 Subject: [PATCH 1/5] Revert "Fixed scroll behavior (#9043)" This reverts commit 9bcd1ea9b8cc5b55692765d40df000da8ddef02b. --- packages/util/src/emulator.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/util/src/emulator.ts b/packages/util/src/emulator.ts index 1c4d4ae7a7d..ff09940d88f 100644 --- a/packages/util/src/emulator.ts +++ b/packages/util/src/emulator.ts @@ -220,7 +220,7 @@ export function updateEmulatorBanner( function setupBannerStyles(bannerEl: HTMLElement): void { bannerEl.style.display = 'flex'; bannerEl.style.background = '#7faaf0'; - bannerEl.style.position = 'fixed'; + bannerEl.style.position = 'absolute'; bannerEl.style.bottom = '5px'; bannerEl.style.left = '5px'; bannerEl.style.padding = '.5em'; From 875a8070ddd207dbbc26ad6299b4ff2a2cb21e5d Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Mon, 19 May 2025 16:40:36 -0700 Subject: [PATCH 2/5] Revert "Add Emulator Overlay (#8977) (#9031)" This reverts commit 8593fa05bd884c2f1f6f3b4ae062efa48af93d24. --- common/api-review/util.api.md | 3 - packages/auth/src/core/auth/emulator.ts | 16 +- packages/auth/src/platform_browser/index.ts | 8 +- packages/database/src/api/Database.ts | 8 +- packages/firestore/src/lite-api/database.ts | 11 +- packages/functions/src/api.ts | 4 +- packages/functions/src/service.ts | 7 +- packages/storage/src/api.ts | 4 +- packages/storage/src/service.ts | 4 +- packages/util/src/emulator.ts | 178 -------------------- 10 files changed, 15 insertions(+), 228 deletions(-) diff --git a/common/api-review/util.api.md b/common/api-review/util.api.md index f263f450da3..427cb5e174a 100644 --- a/common/api-review/util.api.md +++ b/common/api-review/util.api.md @@ -487,9 +487,6 @@ export interface Subscribe { // @public (undocumented) export type Unsubscribe = () => void; -// @public -export function updateEmulatorBanner(name: string, isRunningEmulator: boolean): void; - // Warning: (ae-missing-release-tag) "validateArgCount" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public diff --git a/packages/auth/src/core/auth/emulator.ts b/packages/auth/src/core/auth/emulator.ts index 42fbda3f095..8547f7bad6c 100644 --- a/packages/auth/src/core/auth/emulator.ts +++ b/packages/auth/src/core/auth/emulator.ts @@ -18,12 +18,7 @@ import { Auth } from '../../model/public_types'; import { AuthErrorCode } from '../errors'; import { _assert } from '../util/assert'; import { _castAuth } from './auth_impl'; -import { - deepEqual, - isCloudWorkstation, - pingServer, - updateEmulatorBanner -} from '@firebase/util'; +import { deepEqual, isCloudWorkstation, pingServer } from '@firebase/util'; /** * Changes the {@link Auth} instance to communicate with the Firebase Auth Emulator, instead of production @@ -102,12 +97,13 @@ export function connectAuthEmulator( authInternal.emulatorConfig = emulatorConfig; authInternal.settings.appVerificationDisabledForTesting = true; + if (!disableWarnings) { + emitEmulatorWarning(); + } + + // Workaround to get cookies in Firebase Studio if (isCloudWorkstation(host)) { - updateEmulatorBanner('Auth', true); - // Workaround to get cookies in Firebase Studio void pingServer(`${protocol}//${host}${portStr}`); - } else if (!disableWarnings) { - emitEmulatorWarning(); } } diff --git a/packages/auth/src/platform_browser/index.ts b/packages/auth/src/platform_browser/index.ts index 99ab834cbdb..f94525bfeb7 100644 --- a/packages/auth/src/platform_browser/index.ts +++ b/packages/auth/src/platform_browser/index.ts @@ -30,11 +30,7 @@ import { browserSessionPersistence } from './persistence/session_storage'; import { indexedDBLocalPersistence } from './persistence/indexed_db'; import { browserPopupRedirectResolver } from './popup_redirect'; import { Auth, User } from '../model/public_types'; -import { - getDefaultEmulatorHost, - getExperimentalSetting, - updateEmulatorBanner -} from '@firebase/util'; +import { getDefaultEmulatorHost, getExperimentalSetting } from '@firebase/util'; import { _setExternalJSProvider } from './load_js'; import { _createError } from '../core/util/assert'; import { AuthErrorCode } from '../core/errors'; @@ -114,8 +110,6 @@ export function getAuth(app: FirebaseApp = getApp()): Auth { const authEmulatorHost = getDefaultEmulatorHost('auth'); if (authEmulatorHost) { connectAuthEmulator(auth, `http://${authEmulatorHost}`); - } else { - updateEmulatorBanner('Auth', false); } return auth; diff --git a/packages/database/src/api/Database.ts b/packages/database/src/api/Database.ts index a94b04518d7..515e278b5c5 100644 --- a/packages/database/src/api/Database.ts +++ b/packages/database/src/api/Database.ts @@ -31,8 +31,7 @@ import { EmulatorMockTokenOptions, getDefaultEmulatorHostnameAndPort, isCloudWorkstation, - pingServer, - updateEmulatorBanner + pingServer } from '@firebase/util'; import { AppCheckTokenProvider } from '../core/AppCheckTokenProvider'; @@ -258,10 +257,6 @@ export class Database implements _FirebaseService { this.app.options['databaseAuthVariableOverride'] ); this._instanceStarted = true; - updateEmulatorBanner( - 'Database', - this._repo.repoInfo_.emulatorOptions !== null - ); } return this._repoInternal; } @@ -398,7 +393,6 @@ export function connectDatabaseEmulator( // Workaround to get cookies in Firebase Studio if (isCloudWorkstation(host)) { void pingServer(host); - updateEmulatorBanner('Database', true); } // Modify the repo to apply emulator settings diff --git a/packages/firestore/src/lite-api/database.ts b/packages/firestore/src/lite-api/database.ts index fce6d5843b7..8e7fdb27e90 100644 --- a/packages/firestore/src/lite-api/database.ts +++ b/packages/firestore/src/lite-api/database.ts @@ -28,7 +28,6 @@ import { EmulatorMockTokenOptions, getDefaultEmulatorHostnameAndPort, isCloudWorkstation, - updateEmulatorBanner, pingServer } from '@firebase/util'; @@ -143,7 +142,6 @@ export class Firestore implements FirestoreService { _freezeSettings(): FirestoreSettingsImpl { this._settingsFrozen = true; - updateEmulatorBanner('Firestore', this._settings.isUsingEmulator); return this._settings; } @@ -336,7 +334,9 @@ export function connectFirestoreEmulator( emulatorOptions: firestore._getEmulatorOptions() }; const newHostSetting = `${host}:${port}`; - + if (useSsl) { + void pingServer(`https://${newHostSetting}`); + } if (settings.host !== DEFAULT_HOST && settings.host !== newHostSetting) { logWarn( 'Host has been set in both settings() and connectFirestoreEmulator(), emulator host ' + @@ -357,11 +357,6 @@ export function connectFirestoreEmulator( firestore._setSettings(newConfig); - if (useSsl) { - void pingServer(`https://${newHostSetting}`); - updateEmulatorBanner('Firestore', true); - } - if (options.mockUserToken) { let token: string; let user: User; diff --git a/packages/functions/src/api.ts b/packages/functions/src/api.ts index cb987035145..7f92cba8343 100644 --- a/packages/functions/src/api.ts +++ b/packages/functions/src/api.ts @@ -29,8 +29,7 @@ import { } from './service'; import { getModularInstance, - getDefaultEmulatorHostnameAndPort, - updateEmulatorBanner + getDefaultEmulatorHostnameAndPort } from '@firebase/util'; export { FunctionsError } from './error'; @@ -48,7 +47,6 @@ export function getFunctions( app: FirebaseApp = getApp(), regionOrCustomDomain: string = DEFAULT_REGION ): Functions { - updateEmulatorBanner('Functions', false); // Dependencies const functionsProvider: Provider<'functions'> = _getProvider( getModularInstance(app), diff --git a/packages/functions/src/service.ts b/packages/functions/src/service.ts index 57504a4c7a4..af9d8898d2e 100644 --- a/packages/functions/src/service.ts +++ b/packages/functions/src/service.ts @@ -30,11 +30,7 @@ import { Provider } from '@firebase/component'; import { FirebaseAuthInternalName } from '@firebase/auth-interop-types'; import { MessagingInternalComponentName } from '@firebase/messaging-interop-types'; import { AppCheckInternalComponentName } from '@firebase/app-check-interop-types'; -import { - isCloudWorkstation, - pingServer, - updateEmulatorBanner -} from '@firebase/util'; +import { isCloudWorkstation, pingServer } from '@firebase/util'; export const DEFAULT_REGION = 'us-central1'; @@ -186,7 +182,6 @@ export function connectFunctionsEmulator( // Workaround to get cookies in Firebase Studio if (useSsl) { void pingServer(functionsInstance.emulatorOrigin); - updateEmulatorBanner('Functions', true); } } diff --git a/packages/storage/src/api.ts b/packages/storage/src/api.ts index b164a1324c3..84c77ea0c8c 100644 --- a/packages/storage/src/api.ts +++ b/packages/storage/src/api.ts @@ -53,8 +53,7 @@ import { STORAGE_TYPE } from './constants'; import { EmulatorMockTokenOptions, getModularInstance, - getDefaultEmulatorHostnameAndPort, - updateEmulatorBanner + getDefaultEmulatorHostnameAndPort } from '@firebase/util'; import { StringFormat } from './implementation/string'; @@ -333,7 +332,6 @@ export function getStorage( bucketUrl?: string ): FirebaseStorage { app = getModularInstance(app); - updateEmulatorBanner('Storage', false); const storageProvider: Provider<'storage'> = _getProvider(app, STORAGE_TYPE); const storageInstance = storageProvider.getImmediate({ identifier: bucketUrl diff --git a/packages/storage/src/service.ts b/packages/storage/src/service.ts index 97d1407bb52..741dd6eaa1a 100644 --- a/packages/storage/src/service.ts +++ b/packages/storage/src/service.ts @@ -46,8 +46,7 @@ import { createMockUserToken, EmulatorMockTokenOptions, isCloudWorkstation, - pingServer, - updateEmulatorBanner + pingServer } from '@firebase/util'; import { Connection, ConnectionType } from './implementation/connection'; @@ -151,7 +150,6 @@ export function connectStorageEmulator( // Workaround to get cookies in Firebase Studio if (useSsl) { void pingServer(`https://${storage.host}`); - updateEmulatorBanner('Storage', true); } storage._isUsingEmulator = true; storage._protocol = useSsl ? 'https' : 'http'; diff --git a/packages/util/src/emulator.ts b/packages/util/src/emulator.ts index ff09940d88f..2850b5be378 100644 --- a/packages/util/src/emulator.ts +++ b/packages/util/src/emulator.ts @@ -16,7 +16,6 @@ */ import { base64urlEncodeWithoutPadding } from './crypt'; -import { isCloudWorkstation } from './url'; // Firebase Auth tokens contain snake_case claims following the JWT standard / convention. /* eslint-disable camelcase */ @@ -141,180 +140,3 @@ export function createMockUserToken( signature ].join('.'); } - -interface EmulatorStatusMap { - [name: string]: boolean; -} -const emulatorStatus: EmulatorStatusMap = {}; - -interface EmulatorSummary { - prod: string[]; - emulator: string[]; -} - -// Checks whether any products are running on an emulator -function getEmulatorSummary(): EmulatorSummary { - const summary: EmulatorSummary = { - prod: [], - emulator: [] - }; - for (const key of Object.keys(emulatorStatus)) { - if (emulatorStatus[key]) { - summary.emulator.push(key); - } else { - summary.prod.push(key); - } - } - return summary; -} - -function getOrCreateEl(id: string): { created: boolean; element: HTMLElement } { - let parentDiv = document.getElementById(id); - let created = false; - if (!parentDiv) { - parentDiv = document.createElement('div'); - parentDiv.setAttribute('id', id); - created = true; - } - return { created, element: parentDiv }; -} - -let previouslyDismissed = false; -/** - * Updates Emulator Banner. Primarily used for Firebase Studio - * @param name - * @param isRunningEmulator - * @public - */ -export function updateEmulatorBanner( - name: string, - isRunningEmulator: boolean -): void { - if ( - typeof window === 'undefined' || - typeof document === 'undefined' || - !isCloudWorkstation(window.location.host) || - emulatorStatus[name] === isRunningEmulator || - emulatorStatus[name] || // If already set to use emulator, can't go back to prod. - previouslyDismissed - ) { - return; - } - - emulatorStatus[name] = isRunningEmulator; - - function prefixedId(id: string): string { - return `__firebase__banner__${id}`; - } - const bannerId = '__firebase__banner'; - const summary = getEmulatorSummary(); - const showError = summary.prod.length > 0; - - function tearDown(): void { - const element = document.getElementById(bannerId); - if (element) { - element.remove(); - } - } - - function setupBannerStyles(bannerEl: HTMLElement): void { - bannerEl.style.display = 'flex'; - bannerEl.style.background = '#7faaf0'; - bannerEl.style.position = 'absolute'; - bannerEl.style.bottom = '5px'; - bannerEl.style.left = '5px'; - bannerEl.style.padding = '.5em'; - bannerEl.style.borderRadius = '5px'; - bannerEl.style.alignItems = 'center'; - } - - function setupIconStyles(prependIcon: SVGElement, iconId: string): void { - prependIcon.setAttribute('width', '24'); - prependIcon.setAttribute('id', iconId); - prependIcon.setAttribute('height', '24'); - prependIcon.setAttribute('viewBox', '0 0 24 24'); - prependIcon.setAttribute('fill', 'none'); - prependIcon.style.marginLeft = '-6px'; - } - - function setupCloseBtn(): HTMLSpanElement { - const closeBtn = document.createElement('span'); - closeBtn.style.cursor = 'pointer'; - closeBtn.style.marginLeft = '16px'; - closeBtn.style.fontSize = '24px'; - closeBtn.innerHTML = ' ×'; - closeBtn.onclick = () => { - previouslyDismissed = true; - tearDown(); - }; - return closeBtn; - } - - function setupLinkStyles( - learnMoreLink: HTMLAnchorElement, - learnMoreId: string - ): void { - learnMoreLink.setAttribute('id', learnMoreId); - learnMoreLink.innerText = 'Learn more'; - learnMoreLink.href = - 'https://firebase.google.com/docs/studio/preview-apps#preview-backend'; - learnMoreLink.setAttribute('target', '__blank'); - learnMoreLink.style.paddingLeft = '5px'; - learnMoreLink.style.textDecoration = 'underline'; - } - - function setupDom(): void { - const banner = getOrCreateEl(bannerId); - const firebaseTextId = prefixedId('text'); - const firebaseText: HTMLSpanElement = - document.getElementById(firebaseTextId) || document.createElement('span'); - const learnMoreId = prefixedId('learnmore'); - const learnMoreLink: HTMLAnchorElement = - (document.getElementById(learnMoreId) as HTMLAnchorElement) || - document.createElement('a'); - const prependIconId = prefixedId('preprendIcon'); - const prependIcon: SVGElement = - (document.getElementById( - prependIconId - ) as HTMLOrSVGElement as SVGElement) || - document.createElementNS('http://www.w3.org/2000/svg', 'svg'); - if (banner.created) { - // update styles - const bannerEl = banner.element; - setupBannerStyles(bannerEl); - setupLinkStyles(learnMoreLink, learnMoreId); - const closeBtn = setupCloseBtn(); - setupIconStyles(prependIcon, prependIconId); - bannerEl.append(prependIcon, firebaseText, learnMoreLink, closeBtn); - document.body.appendChild(bannerEl); - } - - if (showError) { - firebaseText.innerText = `Preview backend disconnected.`; - prependIcon.innerHTML = ` - - - - - - -`; - } else { - prependIcon.innerHTML = ` - - - - - - -`; - firebaseText.innerText = 'Preview backend running in this workspace.'; - } - firebaseText.setAttribute('id', firebaseTextId); - } - if (document.readyState === 'loading') { - window.addEventListener('DOMContentLoaded', setupDom); - } else { - setupDom(); - } -} From 658e5c497991c8781f77b7b9b617e979ea1dccf3 Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Mon, 19 May 2025 16:45:04 -0700 Subject: [PATCH 3/5] Undid revert of util --- packages/util/src/emulator.ts | 178 ++++++++++++++++++++++++++++++++++ 1 file changed, 178 insertions(+) diff --git a/packages/util/src/emulator.ts b/packages/util/src/emulator.ts index 2850b5be378..1c4d4ae7a7d 100644 --- a/packages/util/src/emulator.ts +++ b/packages/util/src/emulator.ts @@ -16,6 +16,7 @@ */ import { base64urlEncodeWithoutPadding } from './crypt'; +import { isCloudWorkstation } from './url'; // Firebase Auth tokens contain snake_case claims following the JWT standard / convention. /* eslint-disable camelcase */ @@ -140,3 +141,180 @@ export function createMockUserToken( signature ].join('.'); } + +interface EmulatorStatusMap { + [name: string]: boolean; +} +const emulatorStatus: EmulatorStatusMap = {}; + +interface EmulatorSummary { + prod: string[]; + emulator: string[]; +} + +// Checks whether any products are running on an emulator +function getEmulatorSummary(): EmulatorSummary { + const summary: EmulatorSummary = { + prod: [], + emulator: [] + }; + for (const key of Object.keys(emulatorStatus)) { + if (emulatorStatus[key]) { + summary.emulator.push(key); + } else { + summary.prod.push(key); + } + } + return summary; +} + +function getOrCreateEl(id: string): { created: boolean; element: HTMLElement } { + let parentDiv = document.getElementById(id); + let created = false; + if (!parentDiv) { + parentDiv = document.createElement('div'); + parentDiv.setAttribute('id', id); + created = true; + } + return { created, element: parentDiv }; +} + +let previouslyDismissed = false; +/** + * Updates Emulator Banner. Primarily used for Firebase Studio + * @param name + * @param isRunningEmulator + * @public + */ +export function updateEmulatorBanner( + name: string, + isRunningEmulator: boolean +): void { + if ( + typeof window === 'undefined' || + typeof document === 'undefined' || + !isCloudWorkstation(window.location.host) || + emulatorStatus[name] === isRunningEmulator || + emulatorStatus[name] || // If already set to use emulator, can't go back to prod. + previouslyDismissed + ) { + return; + } + + emulatorStatus[name] = isRunningEmulator; + + function prefixedId(id: string): string { + return `__firebase__banner__${id}`; + } + const bannerId = '__firebase__banner'; + const summary = getEmulatorSummary(); + const showError = summary.prod.length > 0; + + function tearDown(): void { + const element = document.getElementById(bannerId); + if (element) { + element.remove(); + } + } + + function setupBannerStyles(bannerEl: HTMLElement): void { + bannerEl.style.display = 'flex'; + bannerEl.style.background = '#7faaf0'; + bannerEl.style.position = 'fixed'; + bannerEl.style.bottom = '5px'; + bannerEl.style.left = '5px'; + bannerEl.style.padding = '.5em'; + bannerEl.style.borderRadius = '5px'; + bannerEl.style.alignItems = 'center'; + } + + function setupIconStyles(prependIcon: SVGElement, iconId: string): void { + prependIcon.setAttribute('width', '24'); + prependIcon.setAttribute('id', iconId); + prependIcon.setAttribute('height', '24'); + prependIcon.setAttribute('viewBox', '0 0 24 24'); + prependIcon.setAttribute('fill', 'none'); + prependIcon.style.marginLeft = '-6px'; + } + + function setupCloseBtn(): HTMLSpanElement { + const closeBtn = document.createElement('span'); + closeBtn.style.cursor = 'pointer'; + closeBtn.style.marginLeft = '16px'; + closeBtn.style.fontSize = '24px'; + closeBtn.innerHTML = ' ×'; + closeBtn.onclick = () => { + previouslyDismissed = true; + tearDown(); + }; + return closeBtn; + } + + function setupLinkStyles( + learnMoreLink: HTMLAnchorElement, + learnMoreId: string + ): void { + learnMoreLink.setAttribute('id', learnMoreId); + learnMoreLink.innerText = 'Learn more'; + learnMoreLink.href = + 'https://firebase.google.com/docs/studio/preview-apps#preview-backend'; + learnMoreLink.setAttribute('target', '__blank'); + learnMoreLink.style.paddingLeft = '5px'; + learnMoreLink.style.textDecoration = 'underline'; + } + + function setupDom(): void { + const banner = getOrCreateEl(bannerId); + const firebaseTextId = prefixedId('text'); + const firebaseText: HTMLSpanElement = + document.getElementById(firebaseTextId) || document.createElement('span'); + const learnMoreId = prefixedId('learnmore'); + const learnMoreLink: HTMLAnchorElement = + (document.getElementById(learnMoreId) as HTMLAnchorElement) || + document.createElement('a'); + const prependIconId = prefixedId('preprendIcon'); + const prependIcon: SVGElement = + (document.getElementById( + prependIconId + ) as HTMLOrSVGElement as SVGElement) || + document.createElementNS('http://www.w3.org/2000/svg', 'svg'); + if (banner.created) { + // update styles + const bannerEl = banner.element; + setupBannerStyles(bannerEl); + setupLinkStyles(learnMoreLink, learnMoreId); + const closeBtn = setupCloseBtn(); + setupIconStyles(prependIcon, prependIconId); + bannerEl.append(prependIcon, firebaseText, learnMoreLink, closeBtn); + document.body.appendChild(bannerEl); + } + + if (showError) { + firebaseText.innerText = `Preview backend disconnected.`; + prependIcon.innerHTML = ` + + + + + + +`; + } else { + prependIcon.innerHTML = ` + + + + + + +`; + firebaseText.innerText = 'Preview backend running in this workspace.'; + } + firebaseText.setAttribute('id', firebaseTextId); + } + if (document.readyState === 'loading') { + window.addEventListener('DOMContentLoaded', setupDom); + } else { + setupDom(); + } +} From c41a3759b51676fdc6a6832bcd493d02f4e267b7 Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Mon, 19 May 2025 16:47:36 -0700 Subject: [PATCH 4/5] Create dirty-crews-cross.md --- .changeset/dirty-crews-cross.md | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 .changeset/dirty-crews-cross.md diff --git a/.changeset/dirty-crews-cross.md b/.changeset/dirty-crews-cross.md new file mode 100644 index 00000000000..08a962670f0 --- /dev/null +++ b/.changeset/dirty-crews-cross.md @@ -0,0 +1,9 @@ +--- +"@firebase/auth": patch +"@firebase/database": patch +"@firebase/firestore": patch +"@firebase/functions": patch +"@firebase/storage": patch +--- + +Revert "Fixed scroll behavior (#9043)" From 0a71a4643c61cf344a319c1fa21fd90628619230 Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Tue, 20 May 2025 09:48:53 -0700 Subject: [PATCH 5/5] Removed unnecessary markdown file --- common/api-review/util.api.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/common/api-review/util.api.md b/common/api-review/util.api.md index 427cb5e174a..f263f450da3 100644 --- a/common/api-review/util.api.md +++ b/common/api-review/util.api.md @@ -487,6 +487,9 @@ export interface Subscribe { // @public (undocumented) export type Unsubscribe = () => void; +// @public +export function updateEmulatorBanner(name: string, isRunningEmulator: boolean): void; + // Warning: (ae-missing-release-tag) "validateArgCount" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public