Skip to content

Add Emulator Overlay #8977

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 68 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 49 commits
Commits
Show all changes
68 commits
Select commit Hold shift + click to select a range
02c52c6
Added test project to fdc
maneesht Apr 11, 2025
37d0f18
Fixed formatting
maneesht Apr 11, 2025
a4d7813
Fix linting
maneesht Apr 11, 2025
170b15a
Excluded example integration from tsconfig
maneesht Apr 11, 2025
ec405ae
Fixed example-integration package.json
maneesht Apr 11, 2025
248f654
Added ssl check for firestore
maneesht Apr 23, 2025
14ef1bc
Added ssl checks for RTDB
maneesht Apr 23, 2025
a8fe7de
Merge remote-tracking branch 'origin/main' into mtewani/add-ssl-check…
maneesht Apr 23, 2025
df4a115
Removed unnecessary files
maneesht Apr 23, 2025
f867d3b
Removed unnecessary data connect changes
maneesht Apr 23, 2025
4f23f33
Create gentle-laws-kneel.md
maneesht Apr 23, 2025
55b1c0a
Added code to pass on credentials if using a cloud workstation
maneesht Apr 23, 2025
e0a59c5
Create nine-pugs-crash.md
maneesht Apr 23, 2025
8d93780
Addressed comments
maneesht Apr 24, 2025
78142b9
Merge branch 'mtewani/fix-auth-redirects-studio' of https://github.co…
maneesht Apr 24, 2025
5e76a0a
Removed unused import
maneesht Apr 24, 2025
b8b485d
include storage changes
maneesht Apr 24, 2025
21ecf95
Updated api review
maneesht Apr 24, 2025
24c1575
Removed unnecessary import
maneesht Apr 25, 2025
7c7f3ae
Fix formatting
maneesht Apr 25, 2025
d62409a
Fixed data connect test
maneesht Apr 25, 2025
82faa08
Included extra url in externs
maneesht Apr 25, 2025
32c461a
Fixed fdc tests
maneesht Apr 25, 2025
da5b7bf
Passed in emulator information
maneesht Apr 25, 2025
b424e58
Fixed formattign
maneesht Apr 25, 2025
7d2313f
WIP
maneesht Apr 25, 2025
6e0761d
Added emulator status
maneesht Apr 25, 2025
e7b292d
Removed firebaseapp import
maneesht Apr 25, 2025
beff97f
Merge remote-tracking branch 'origin/main' into mtewani/add-emulator-…
maneesht May 1, 2025
6ca5c24
Removed app check change
maneesht May 1, 2025
6d0af9d
Removed eslintrc change
maneesht May 1, 2025
445c490
Removed unnecessary test
maneesht May 1, 2025
d97337f
Fixed failing tests
maneesht May 1, 2025
8f6167e
WIP
maneesht May 5, 2025
0aede90
Implemented emulator overlay
maneesht May 5, 2025
0d05eeb
Merge remote-tracking branch 'origin/main' into mtewani/add-emulator-…
maneesht May 5, 2025
fa3a56f
Removed changeset
maneesht May 5, 2025
6cff61f
Create three-singers-wonder.md
maneesht May 5, 2025
9a4d8ba
Merge branch 'mtewani/add-emulator-overlay' of https://github.com/fir…
maneesht May 5, 2025
eeebee1
Removed unused line
maneesht May 5, 2025
c439abe
Removed unnecessary changes
maneesht May 5, 2025
adb9c76
Updated storage changeset
maneesht May 5, 2025
32433f3
Fixed button click
maneesht May 5, 2025
1db0a40
Fixed linting errors
maneesht May 5, 2025
25f3a21
fixed formatting
maneesht May 5, 2025
b0e7566
Addressed comments
maneesht May 5, 2025
8d70b12
Removed extra document check
maneesht May 5, 2025
bffdabd
Removed extra export
maneesht May 5, 2025
cdbf663
Trigger Build
maneesht May 5, 2025
927dadd
Fixed formatting
maneesht May 5, 2025
83b84f0
Addressed comments
maneesht May 6, 2025
c824b35
Fixed linting
maneesht May 6, 2025
9ee4aa0
Fixed linting
maneesht May 6, 2025
1e7039a
Updated to only trigger on Studio
maneesht May 6, 2025
2e57ab7
Fixed linting
maneesht May 6, 2025
c2246ca
Trigger Build
maneesht May 6, 2025
fe1264c
Persisted dismiss
maneesht May 6, 2025
a3edf83
Removed change to check every request
maneesht May 7, 2025
db73a96
Used disableWarnings in auth
maneesht May 7, 2025
1c4c6ee
Fixed linting
maneesht May 7, 2025
3a4ba47
Fixed linting
maneesht May 8, 2025
613bd04
Updated for copy
maneesht May 8, 2025
243d24d
Removed testing changed
maneesht May 8, 2025
0da1b9f
Updated to include external link
maneesht May 8, 2025
3d0a24f
Added back emulator banner change
maneesht May 8, 2025
c553d99
Added back emulator banner change
maneesht May 8, 2025
e5a945c
Fixed linting
maneesht May 8, 2025
a528caf
Removed trace
maneesht May 8, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .changeset/three-singers-wonder.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@firebase/auth": patch
"@firebase/firestore": patch
"@firebase/util": patch
---

Add Emulator Overlay
3 changes: 3 additions & 0 deletions common/api-review/util.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -482,6 +482,9 @@ export interface Subscribe<T> {
// @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
Expand Down
7 changes: 5 additions & 2 deletions packages/auth/src/api/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ import {
FirebaseError,
isCloudflareWorker,
isCloudWorkstation,
querystring
querystring,
updateEmulatorBanner
} from '@firebase/util';

import { AuthErrorCode, NamedErrorParams } from '../core/errors';
Expand Down Expand Up @@ -198,7 +199,9 @@ export async function _performFetchWithErrorHandling<V>(
customErrorMap: Partial<ServerErrorMap<ServerError>>,
fetchFn: () => Promise<Response>
): Promise<V> {
(auth as AuthInternal)._canInitEmulator = false;
const authInternal = auth as AuthInternal;
updateEmulatorBanner('Auth', authInternal.emulatorConfig !== null);
authInternal._canInitEmulator = false;
const errorMap = { ...SERVER_ERROR_MAP, ...customErrorMap };
try {
const networkTimeout = new NetworkTimeout<Response>(auth);
Expand Down
10 changes: 8 additions & 2 deletions packages/auth/src/core/auth/emulator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,12 @@ import { Auth } from '../../model/public_types';
import { AuthErrorCode } from '../errors';
import { _assert } from '../util/assert';
import { _castAuth } from './auth_impl';
import { deepEqual, isCloudWorkstation, pingServer } from '@firebase/util';
import {
deepEqual,
isCloudWorkstation,
pingServer,
updateEmulatorBanner
} from '@firebase/util';

/**
* Changes the {@link Auth} instance to communicate with the Firebase Auth Emulator, instead of production
Expand Down Expand Up @@ -97,13 +102,14 @@ export function connectAuthEmulator(
authInternal.emulatorConfig = emulatorConfig;
authInternal.settings.appVerificationDisabledForTesting = true;

if (!disableWarnings) {
if (!disableWarnings && !isCloudWorkstation(host)) {
emitEmulatorWarning();
}

// Workaround to get cookies in Firebase Studio
if (isCloudWorkstation(host)) {
void pingServer(`${protocol}//${host}${portStr}`);
updateEmulatorBanner('Auth', true);
}
}

Expand Down
15 changes: 12 additions & 3 deletions packages/firestore/src/lite-api/database.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import {
EmulatorMockTokenOptions,
getDefaultEmulatorHostnameAndPort,
isCloudWorkstation,
updateEmulatorBanner,
pingServer
} from '@firebase/util';

Expand Down Expand Up @@ -142,6 +143,11 @@ export class Firestore implements FirestoreService {

_freezeSettings(): FirestoreSettingsImpl {
this._settingsFrozen = true;
updateEmulatorBanner(
'Firestore',
(this._settings as PrivateSettings).emulatorOptions !== null &&
(this._settings as PrivateSettings).emulatorOptions !== undefined
);
return this._settings;
}

Expand Down Expand Up @@ -334,9 +340,7 @@ 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 ' +
Expand All @@ -357,6 +361,11 @@ export function connectFirestoreEmulator(

firestore._setSettings(newConfig);

if (useSsl) {
void pingServer(`https://${newHostSetting}`);
updateEmulatorBanner('firestore', true);
}

if (options.mockUserToken) {
let token: string;
let user: User;
Expand Down
96 changes: 96 additions & 0 deletions packages/util/src/emulator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,3 +140,99 @@ export function createMockUserToken(
signature
].join('.');
}

interface EmulatorStatuses {
[name: string]: boolean;
}
const emulatorStatus: EmulatorStatuses = {};

// Checks whether any products are running on an emulator
function areRunningEmulator(): boolean {
let runningEmulator = false;
for (const key of Object.keys(emulatorStatus)) {
if (emulatorStatus[key]) {
runningEmulator = true;
}
}
return runningEmulator;
}

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 };
}

/**
* 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' ||
emulatorStatus[name] === isRunningEmulator
) {
return;
}

emulatorStatus[name] = isRunningEmulator;
const bannerId = '__firebase__banner';
if (!areRunningEmulator()) {
tearDown();
return;
}

function tearDown(): void {
const element = document.getElementById(bannerId);
if (element) {
element.remove();
}
}

function setupDom(): void {
const banner = getOrCreateEl(bannerId);
const firebaseText: HTMLSpanElement =
document.getElementById('__firebase__text') ||
document.createElement('span');
if (banner.created) {
// update styles
const bannerEl = banner.element;
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.alignContent = 'center';
const closeBtn = document.createElement('span');
closeBtn.style.cursor = 'pointer';
closeBtn.style.paddingLeft = '5px';
closeBtn.innerHTML = ' &times;';
closeBtn.onclick = () => {
tearDown();
};
bannerEl.appendChild(firebaseText);
bannerEl.appendChild(closeBtn);
document.body.appendChild(banner.element);
}
firebaseText.setAttribute('id', '__firebase__text');
firebaseText.innerText = 'Running in this workspace';
}
if (document.readyState === 'loading') {
window.addEventListener('DOMContentLoaded', setupDom);
} else {
setupDom();
}
}
Loading