Skip to content
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

Vscode emulators #6256

Merged
merged 9 commits into from
Aug 28, 2023
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
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
32 changes: 31 additions & 1 deletion firebase-vscode/src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,15 @@ import { currentOptions, getCommandOptions } from "./options";
import { setInquirerOptions } from "./stubs/inquirer-stub";
import { ServiceAccount } from "../common/types";
import { listChannels } from "../../src/hosting/api";
import { ChannelWithId } from "../common/messaging/types";
import { EmulatorUiSelections, ChannelWithId } from "../common/messaging/types";
import { pluginLogger } from "./logger-wrapper";
import { Config } from "../../src/config";
import { currentUser } from "./workflow";
import { setAccessToken } from "../../src/apiv2";
import { startAll as startAllEmulators, cleanShutdown as stopAllEmulators } from "../../src/emulator/controller";
import { EmulatorRegistry } from "../../src/emulator/registry";
import { EmulatorInfo, Emulators } from "../../src/emulator/types";
import * as commandUtils from "../../src/emulator/commandUtils";

/**
* Try to get a service account by calling requireAuth() without
Expand Down Expand Up @@ -289,3 +293,29 @@ export async function deployToHosting(
}
return { success: true, hostingUrl: "", consoleUrl: "" };
}

export async function emulatorsStart(emulatorUiSelections: EmulatorUiSelections) {
const commandOptions = await getCommandOptions(undefined, {
...currentOptions,
project: emulatorUiSelections.projectId,
exportOnExit: emulatorUiSelections.exportStateOnExit,
import: emulatorUiSelections.importStateFolderPath,
only: emulatorUiSelections.mode === "hosting" ? "hosting" : ""
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we make an enum for modes? eventually we'll add firemat :)

});
// Adjusts some options, export on exit can be a boolean or a path.
commandUtils.setExportOnExitOptions(commandOptions as commandUtils.ExportOnExitOptions);
return startAllEmulators(commandOptions, /*showUi=*/ true);
}

export async function stopEmulators() {
await stopAllEmulators();
}

export function listRunningEmulators(): EmulatorInfo[] {
christhompsongoogle marked this conversation as resolved.
Show resolved Hide resolved
return EmulatorRegistry.listRunningWithInfo();
}

export function getEmulatorUiUrl(): string | undefined {
const url: URL = EmulatorRegistry.url(Emulators.UI);
return url.hostname === "unknown" ? undefined : url.toString();
}
7 changes: 7 additions & 0 deletions firebase-vscode/src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
import { setupSidebar } from "./sidebar";
import { setupWorkflow } from "./workflow";
import { pluginLogger } from "./logger-wrapper";
import { onShutdown } from "./workflow";

const broker = createBroker<
ExtensionToWebviewParamsMap,
Expand All @@ -25,3 +26,9 @@ export function activate(context: vscode.ExtensionContext) {
setupWorkflow(context, broker);
setupSidebar(context, broker);
}

// This method is called when the extension is deactivated
export async function deactivate() {
// This await is optimistic but it might wait for a moment longer while we run cleanup activities
await onShutdown();
}
48 changes: 48 additions & 0 deletions firebase-vscode/src/workflow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ import {
listProjects,
login,
logoutUser,
stopEmulators,
listRunningEmulators,
getEmulatorUiUrl,
emulatorsStart
} from "./cli";
import { User } from "../../src/types/auth";
import { currentOptions } from "./options";
Expand Down Expand Up @@ -230,6 +234,43 @@ export async function setupWorkflow(
broker.send("notifyPreviewChannelResponse", { id: response });
});

broker.on(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we want all the emulator registration in workflow (what does workflow mean)? I think the amount of code warrants an emulator.ts file.

"launchEmulators",
async ({ emulatorUiSelections }) => {
await emulatorsStart(emulatorUiSelections);
broker.send("notifyRunningEmulatorInfo", { uiUrl: getEmulatorUiUrl(), displayInfo: listRunningEmulators() });
}
);

broker.on(
"stopEmulators",
async () => {
await stopEmulators();
// Update the UI
broker.send("notifyEmulatorsStopped");
}
);

broker.on(
"selectEmulatorImportFolder",
async () => {
const options: vscode.OpenDialogOptions = {
canSelectMany: false,
openLabel: `Pick an import folder`,
title: `Pick an import folder`,
canSelectFiles: false,
canSelectFolders: true,
};
const fileUri = await vscode.window.showOpenDialog(options);
// Update the UI of the selection
if (!fileUri || fileUri.length < 1) {
vscode.window.showErrorMessage("Invalid import folder selected.");
return;
}
broker.send("notifyEmulatorImportFolder", { folder: fileUri[0].fsPath });
}
);

context.subscriptions.push(
setupFirebaseJsonAndRcFileSystemWatcher(broker, context)
);
Expand Down Expand Up @@ -346,3 +387,10 @@ export async function setupWorkflow(
}
}
}

/**
* Cleans up any open resources before shutting down.
*/
export async function onShutdown() {
await stopEmulators();
}
22 changes: 22 additions & 0 deletions firebase-vscode/webpack.common.js
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,28 @@ const extensionConfig = {
],
},
},
{
test: /\.js$/,
loader: "string-replace-loader",
options: {
multiple: [
// firebase-tools/node_modules/superstatic/lib/utils/patterns.js
// Stub out the optional RE2 dependency
// TODO: copy the dependency into dist instead of removing them via search/replace.
{
search: 'RE2 = require("re2");',
replace: 'RE2 = null;'
},
// firebase-tools/node_modules/superstatic/lib/middleware/index.js
// Stub out these runtime requirements
// TODO: copy the dependencies into dist instead of removing them via search/replace.
{
search: 'const mware = require("./" + _.kebabCase(name))(spec, config);',
replace: 'return "";'
}
],
}
}
],
},
plugins: [
Expand Down
9 changes: 9 additions & 0 deletions firebase-vscode/webviews/SidebarApp.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { ServiceAccountUser } from "../common/types";
import { DeployPanel } from "./components/DeployPanel";
import { HostingInitState, DeployState } from "./webview-types";
import { ChannelWithId } from "./messaging/types";
import { EmulatorPanel } from "./components/EmulatorPanel";

import { webLogger } from "./globals/web-logger";
import { InitFirebasePanel } from "./components/InitPanel";
Expand Down Expand Up @@ -156,6 +157,14 @@ export function SidebarApp() {
setHostingInitState={setHostingInitState}
/>
)}
{
// Only load the emulator panel if we have a user, firebase.json and this isn't Monospace
// The user login requirement can be removed in the future but the panel will have to
// be restricted to full-offline emulation only.
!!user && !!firebaseJson && !env?.isMonospace && (
<EmulatorPanel firebaseJson={firebaseJson} projectId={projectId} />
)
}
</>
);
}
Loading