|
16 | 16 | */
|
17 | 17 |
|
18 | 18 | import { base64urlEncodeWithoutPadding } from './crypt';
|
| 19 | +import { FirebaseApp } from '@firebase/app'; |
19 | 20 |
|
20 | 21 | // Firebase Auth tokens contain snake_case claims following the JWT standard / convention.
|
21 | 22 | /* eslint-disable camelcase */
|
@@ -140,3 +141,64 @@ export function createMockUserToken(
|
140 | 141 | signature
|
141 | 142 | ].join('.');
|
142 | 143 | }
|
| 144 | + |
| 145 | +function getOrCreate(id: string): { created: boolean; element: HTMLElement } { |
| 146 | + let parentDiv = document.getElementById(id); |
| 147 | + let created = false; |
| 148 | + if (!parentDiv) { |
| 149 | + parentDiv = document.createElement('div'); |
| 150 | + parentDiv.setAttribute('id', id); |
| 151 | + created = true; |
| 152 | + } |
| 153 | + return { created, element: parentDiv }; |
| 154 | +} |
| 155 | + |
| 156 | +export interface EmulatorStatus { |
| 157 | + name: string; |
| 158 | + isRunningEmulator: boolean; |
| 159 | +} |
| 160 | +export function updateStatus( |
| 161 | + emulatorStatus: EmulatorStatus, |
| 162 | + isCloudWorkstation: boolean |
| 163 | +) { |
| 164 | + function setupDom() { |
| 165 | + const parentDivId = `__firebase_status`; |
| 166 | + |
| 167 | + let { element: parentDiv, created } = getOrCreate(parentDivId); |
| 168 | + |
| 169 | + if (created) { |
| 170 | + parentDiv.style.position = 'fixed'; |
| 171 | + parentDiv.style.bottom = '0px'; |
| 172 | + parentDiv.style.border = 'solid 1px'; |
| 173 | + parentDiv.style.width = '100%'; |
| 174 | + parentDiv.style.borderRadius = '10px'; |
| 175 | + parentDiv.style.padding = '.5em'; |
| 176 | + parentDiv.style.textAlign = 'center'; |
| 177 | + document.body.appendChild(parentDiv); |
| 178 | + } |
| 179 | + |
| 180 | + const { name, isRunningEmulator } = emulatorStatus; |
| 181 | + const { element, created: productDivCreated } = getOrCreate( |
| 182 | + `${parentDivId}_${name}` |
| 183 | + ); |
| 184 | + // If in prod, and not using a cloud workstation, we should remove the node, as the banner can be distracting. |
| 185 | + if (!isRunningEmulator && !isCloudWorkstation) { |
| 186 | + element.remove(); |
| 187 | + return; |
| 188 | + } |
| 189 | + if (productDivCreated) { |
| 190 | + parentDiv.appendChild(element); |
| 191 | + } |
| 192 | + element.style.color = isRunningEmulator ? 'green' : 'red'; |
| 193 | + element.innerHTML = `${name} is running in ${ |
| 194 | + isRunningEmulator ? 'emulator' : 'prod' |
| 195 | + } mode`; |
| 196 | + } |
| 197 | + if (typeof window !== 'undefined' && typeof document !== 'undefined') { |
| 198 | + if (document.readyState === 'loading') { |
| 199 | + window.addEventListener('DOMContentLoaded', setupDom); |
| 200 | + } else { |
| 201 | + setupDom(); |
| 202 | + } |
| 203 | + } |
| 204 | +} |
0 commit comments