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

Add support for emulator import/export in VSCode #8053

Open
wants to merge 41 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
26241ce
Added config
joehan Oct 10, 2024
094164a
Merge remote-tracking branch 'public/master' into jh-persistence-prot…
joehan Oct 15, 2024
6e03ec1
Adding basic persistence support
joehan Oct 15, 2024
6c9834d
formats
joehan Oct 15, 2024
872b150
Merge branch 'master' into jh-persistence-prototype
joehan Oct 17, 2024
d8355f3
Merge remote-tracking branch 'public/master' into jh-persistence-prot…
joehan Oct 25, 2024
31560d9
Starting on clearData
joehan Oct 28, 2024
84074cf
Merge remote-tracking branch 'public/master' into jh-persistence-prot…
joehan Nov 14, 2024
f510a73
Clear data now working!
joehan Nov 14, 2024
5d046cf
Added import/export support
joehan Nov 15, 2024
79f651c
Merge branch 'master' into jh-persistence-prototype
joehan Nov 15, 2024
1a13dfa
PR fixes + fidelity to approved API'
joehan Nov 15, 2024
9c9e139
Merge branch 'jh-persistence-prototype' of github.com:firebase/fireba…
joehan Nov 15, 2024
8b56148
Merging master
joehan Nov 15, 2024
0fe172f
Trying to fix vsce compile
joehan Nov 18, 2024
45fdcc2
Merge branch 'master' into jh-persistence-prototype
joehan Nov 18, 2024
6aa6e98
Progress on vsce import/export/clearData UI
joehan Nov 19, 2024
c6f7ada
fixed build issue
joehan Nov 21, 2024
b5b7d2b
Merge remote-tracking branch 'public/master' into jh-import-export-vsce
joehan Nov 22, 2024
ba3c83d
Merge remote-tracking branch 'public/master' into jh-import-export-vsce
joehan Dec 6, 2024
4a73f32
Merge remote-tracking branch 'public/master' into jh-import-export-vsce
joehan Dec 10, 2024
4f725b6
Adding config options for importPath/exportPath/exportOnExit
joehan Dec 10, 2024
50a10a8
More fixes
joehan Dec 10, 2024
cc4680e
add changelog
joehan Dec 11, 2024
69169ec
Merge conflict
joehan Dec 11, 2024
545557c
Tweak the emulator action-buttons
tjlav5 Dec 11, 2024
7f8800f
Startign on tests
joehan Dec 13, 2024
9f41ee8
Merging master
joehan Jan 2, 2025
4b5d2c6
Merge branch 'jh-import-export-vsce' of github.com:firebase/firebase-…
joehan Jan 2, 2025
ef1dd31
Adding basic tests for export and clear'
joehan Jan 3, 2025
a4fef1c
Merge branch 'master' into jh-import-export-vsce
joehan Jan 3, 2025
76f7707
format
joehan Jan 3, 2025
7688793
ajv upgrade
joehan Jan 3, 2025
5bd2ab3
Merge branch 'master' into jh-import-export-vsce
joehan Jan 9, 2025
75c2f5e
Merge branch 'master' into jh-import-export-vsce
joehan Jan 9, 2025
2bfaadb
Fix config issue
joehan Jan 15, 2025
c17e921
Fix typo
joehan Jan 15, 2025
83d6524
Santiy checking terminalView - does this even resolve?
joehan Jan 15, 2025
e962c12
Merge branch 'master' into jh-import-export-vsce
joehan Jan 16, 2025
4fe94da
Does it work as a single test?
joehan Jan 16, 2025
3350cc8
PR fixes
joehan Jan 16, 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
3 changes: 2 additions & 1 deletion firebase-vscode/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
## NEXT

- [Feature] Added `debug` setting to run commands with `--debug`
- [Added] Added support for emulator import/export.
- [Added] Added `debug` setting to run commands with `--debug`

## 0.12.0

Expand Down
11 changes: 10 additions & 1 deletion firebase-vscode/common/messaging/protocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,12 @@ export interface WebviewToExtensionParamsMap {
/** Calls the `firebase init` CLI */
runFirebaseInit: void;

/** Calls the `firebase init` CLI */
/** Calls the `firebase emulators:start` CLI */
runStartEmulators: void;

/** Calls the `firebase emulators:export` CLI */
runEmulatorsExport: void;

/**
* Show a UI message using the vscode interface
*/
Expand Down Expand Up @@ -100,6 +103,12 @@ export interface WebviewToExtensionParamsMap {
/** Opens generated docs */
"fdc.open-docs": void;

/** Opens settings page searching for Data Connect emualtor settings */
"fdc.open-emulator-settings": void;

/** Clears data from a running data connect emulator */
"fdc.clear-emulator-data": void;

// Initialize "result" tab.
getDataConnectResults: void;

Expand Down
14 changes: 14 additions & 0 deletions firebase-vscode/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,20 @@
"markdownDescription": "%ext.config.idx.viewMetricNotice%",
"scope": "application"
},
"firebase.emulators.importPath": {
"type": "string",
"markdownDescription": "%ext.config.emulators.importPath%"
},
"firebase.emulators.exportPath": {
"type": "string",
"default": "./exportedData",
"markdownDescription": "%ext.config.emulators.exportPath%"
},
"firebase.emulators.exportOnExit":{
"type": "boolean",
"default": false,
"markdownDescription": "%ext.config.emulators.exportOnExit%"
},
"firebase.debug": {
"type": "boolean",
"default": false,
Expand Down
7 changes: 5 additions & 2 deletions firebase-vscode/package.nls.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@
"ext.config.firebasePath": "Path to the `Firebase` module, e.g. `./node_modules/firebase`",
"ext.config.hosting.useFrameworks": "Enable web frameworks",
"ext.config.npmPath": "Path to NPM executable in local environment",
"ext.config.title": "Firebase Data Connect",
"ext.config.idx.viewMetricNotice": "Show data collection notice on next startup (IDX Only)",
"ext.config.emulators.importPath": "Path to import emulator data from",
"ext.config.emulators.exportPath": "Path to export emulator data to",
"ext.config.emulators.exportOnExit": "If true, data will be exported to exportPath when the emulator shuts down"
"ext.config.debug": "When true, add the --debug flag to any commands run by the extension",
"ext.config.title": "Prettier",
"ext.config.idx.viewMetricNotice": "Show data collection notice on next startup (IDX Only)"
}
1 change: 1 addition & 0 deletions firebase-vscode/src/analytics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export enum DATA_CONNECT_EVENT_NAME {
START_EMULATORS = "start_emulators",
AUTO_COMPLETE = "auto_complete",
SESSION_CHAR_COUNT = "session_char_count",
EMULATOR_EXPORT ="emulator_export",
SETUP_FIREBASE_BINARY = "setup_firebase_binary",
}

Expand Down
71 changes: 64 additions & 7 deletions firebase-vscode/src/core/emulators.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import { EmulatorHubClient } from "../../../src/emulator/hubClient";
import { GetEmulatorsResponse } from "../../../src/emulator/hub";
import { EmulatorInfo } from "../emulator/types";
import { getSettings } from "../utils/settings";
export class EmulatorsController implements Disposable {
constructor(private broker: ExtensionBrokerImpl) {
this.emulatorStatusItem.command = "firebase.openFirebaseRc";
Expand All @@ -21,6 +22,25 @@
this.setEmulatorsStarting();
}),
);

// Subscription to open up settings window
this.subscriptions.push(
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: these are very simple so it's ok; but prefer named function OR comments describing these; Otherwise sifting through subscriptions gets difficult

broker.on("fdc.open-emulator-settings", () => {
vscode.commands.executeCommand( 'workbench.action.openSettings', 'firebase.emulators' );
})
);

// Subscription to trigger clear emulator data when button is clicked.
this.subscriptions.push(
broker.on("fdc.clear-emulator-data", () => {
vscode.commands.executeCommand("firebase.emulators.clearData");
}),
);

// Subscription to trigger emulator exports when button is clicked.
this.subscriptions.push(broker.on("runEmulatorsExport", () => {
vscode.commands.executeCommand("firebase.emulators.exportData")

Check warning on line 42 in firebase-vscode/src/core/emulators.ts

View workflow job for this annotation

GitHub Actions / lint (20)

Missing semicolon

Check warning on line 42 in firebase-vscode/src/core/emulators.ts

View workflow job for this annotation

GitHub Actions / lint (20)

Missing semicolon
}));
}

readonly emulatorStatusItem = vscode.window.createStatusBarItem("emulators");
Expand All @@ -39,6 +59,17 @@
this.setEmulatorsStopped.bind(this),
);

private readonly clearEmulatorDataCommand = vscode.commands.registerCommand(
"firebase.emulators.clearData",
this.clearDataConnectData.bind(this),
);


private readonly exportEmulatorDataCommand = vscode.commands.registerCommand(
"firebase.emulators.exportData",
this.exportEmulatorData.bind(this),
);

readonly emulators: { status: EmulatorsStatus; infos?: RunningEmulatorInfo } =
{
status: "stopped",
Expand Down Expand Up @@ -107,23 +138,47 @@
async findRunningCliEmulators(): Promise<
{ status: EmulatorsStatus; infos?: RunningEmulatorInfo } | undefined
> {
const projectId = firebaseRC.value?.tryReadValue?.projects?.default;
// TODO: think about what to without projectID, in potentially a logged out mode
const hubClient = new EmulatorHubClient(projectId!);

if (hubClient.foundHub()) {
const hubClient = this.getHubClient();
if (hubClient) {
const response: GetEmulatorsResponse = await hubClient.getEmulators();

if (Object.values(response)) {
this.setEmulatorsRunningInfo(Object.values(response));
} else {
this.setEmulatorsStopped();
}
}
return this.emulators;
}

async clearDataConnectData(): Promise<void> {
const hubClient = this.getHubClient();
if (hubClient) {
await hubClient.clearDataConnectData();
vscode.window.showInformationMessage(`Data Connect emulator data has been cleared.`);
}
}

async exportEmulatorData(): Promise<void> {
const settings = getSettings();
const exportDir = settings.exportPath;
const hubClient = this.getHubClient();
if (hubClient) {
// TODO: Make exportDir configurable
await hubClient.postExport({path: exportDir, initiatedBy: "Data Connect VSCode extension"});
vscode.window.showInformationMessage(`Emulator Data exported to ${exportDir}`);
}
}

private getHubClient(): EmulatorHubClient | undefined {
const projectId = firebaseRC.value?.tryReadValue?.projects?.default;
// TODO: think about what to without projectID, in potentially a logged out mode
const hubClient = new EmulatorHubClient(projectId!);
if (hubClient.foundHub()) {
return hubClient;
} else {
this.setEmulatorsStopped();
}

return this.emulators;
}

public areEmulatorsRunning() {
Expand All @@ -135,5 +190,7 @@
this.findRunningEmulatorsCommand.dispose();
this.emulatorStatusItem.dispose();
this.emulatorsStoppped.dispose();
this.clearEmulatorDataCommand.dispose();
this.exportEmulatorDataCommand.dispose();
}
hlshen marked this conversation as resolved.
Show resolved Hide resolved
}
15 changes: 11 additions & 4 deletions firebase-vscode/src/data-connect/terminal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,12 +90,19 @@ export function registerTerminalTasks(

const startEmulatorsTaskBroker = broker.on("runStartEmulators", () => {
analyticsLogger.logger.logUsage(DATA_CONNECT_EVENT_NAME.START_EMULATORS);
// TODO: optional debug mode

let cmd = `${settings.firebasePath} emulators:start --project ${currentProjectId.value}`;

if (settings.importPath) {
cmd += ` --import ${settings.importPath}`;
}
if (settings.exportOnExit) {
cmd += ` --export-on-exit ${settings.exportPath}`;
}
runTerminalTask(
"firebase emulators",
`${settings.firebasePath} emulators:start --project ${currentProjectId.value}`,
// emulators:start almost never ask interactive questions.
{ focus: false },
cmd,
{ focus: true },
);
});

Expand Down
14 changes: 14 additions & 0 deletions firebase-vscode/src/test/integration/fishfood/emulator.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import { firebaseSuite, firebaseTest } from "../../utils/test_hooks";
import { FirebaseCommands } from "../../utils/page_objects/commands";
import { FirebaseSidebar } from "../../utils/page_objects/sidebar";

import { TerminalView } from "../../utils/page_objects/terminal";
import { Notifications } from "../../utils/page_objects/notifications";
import { mockUser } from "../../utils/user";
import { mockProject } from "../../utils/projects";

Expand All @@ -12,6 +15,8 @@ firebaseSuite("Emulators", async function () {

const sidebar = new FirebaseSidebar(workbench);
const commands = new FirebaseCommands();
const terminal = new TerminalView(workbench);
const notifications = new Notifications(workbench);

await sidebar.openExtensionSidebar();
await commands.waitForUser();
Expand All @@ -26,6 +31,15 @@ firebaseSuite("Emulators", async function () {
const current = await sidebar.currentEmulators();

expect(current).toContain("dataconnect :9399");

await sidebar.clearEmulatorData();
const text = await terminal.getTerminalText();
expect(text.includes("Clearing data from Data Connect data sources")).toBeTruthy();

await sidebar.exportEmulatorData();
const exportNotification = await notifications.getExportNotification();
expect(exportNotification).toExist();

},
);
});
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"projects": {
"default": "dart-firebase-admin"
"default": "test-project"
},
"targets": {},
"etags": {},
Expand Down
13 changes: 13 additions & 0 deletions firebase-vscode/src/test/utils/page_objects/notifications.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { Workbench } from "wdio-vscode-service";

export class Notifications {
constructor(readonly workbench: Workbench) {}

async getExportNotification() {
const notifications = await this.workbench.getNotifications();
return notifications.find(async n => {
const message = await n.getMessage();
return message.includes("Emulator Data exported to");
});
}
}
22 changes: 22 additions & 0 deletions firebase-vscode/src/test/utils/page_objects/sidebar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,20 @@ export class FirebaseSidebar {
});
}

async clearEmulatorData() {
return this.runInStudioContext(async (studio) => {
const btn = await studio.clearEmulatorDataBtn;
return btn.click();
});
}

async exportEmulatorData() {
return this.runInStudioContext(async (studio) => {
const btn = await studio.exportEmulatorDataBtn;
return btn.click();
});
}

async startDeploy() {
return this.runInStudioContext(async (studio) => {
await studio.fdcDeployElement.waitForDisplayed();
Expand Down Expand Up @@ -86,6 +100,14 @@ export class StudioView {
return $("vscode-button=Start emulators");
}

get clearEmulatorDataBtn() {
return $("vscode-button=Clear Data Connect data");
}

get exportEmulatorDataBtn() {
return $("vscode-button=Export emulator data");
}

get addSdkToAppBtn() {
return $("vscode-button=Add SDK to app");
}
Expand Down
11 changes: 11 additions & 0 deletions firebase-vscode/src/test/utils/page_objects/terminal.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { Workbench } from "wdio-vscode-service";

export class TerminalView {
constructor(readonly workbench: Workbench) {}

private readonly bottomBar = this.workbench.getBottomBar();
async getTerminalText() {
const tv = await this.bottomBar.openTerminalView();
return tv.getText();
}
}
6 changes: 6 additions & 0 deletions firebase-vscode/src/utils/settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ export interface Settings {
readonly npmPath: string;
readonly useFrameworks: boolean;
readonly shouldShowIdxMetricNotice: boolean;
readonly importPath?: string;
readonly exportPath: string;
readonly exportOnExit: boolean;
readonly debug: boolean;
}

Expand Down Expand Up @@ -38,6 +41,9 @@ export function getSettings(): Settings {
"idx.viewMetricNotice",
true,
),
importPath: config.get<string>("emulators.importPath"),
exportPath: config.get<string>("emulators.exportPath", "./exportedData"),
exportOnExit: config.get<boolean>("emulators.exportOnExit", false),
debug: config.get<boolean>("debug", false),
};
}
Expand Down
7 changes: 7 additions & 0 deletions firebase-vscode/webviews/SidebarApp.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,13 @@ function EmulatorsPanel() {
Start emulators
</VSCodeButton>
<Spacer size="xsmall" />
<Label level={3}>
<a onClick={() => {
broker.send("fdc.open-emulator-settings")
}}>
Configure emulator
</a>
</Label>
<Label level={3}>
See also:{" "}
<a href="https://firebase.google.com/docs/emulator-suite">
Expand Down
6 changes: 6 additions & 0 deletions firebase-vscode/webviews/components/EmulatorPanel.scss
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
@import "../globals/index.scss";

.list {
list-style: none;
}

.fullWidth {
width: 100%;
}

.list-item {
align-items: center;
display: flex;
Expand Down
Loading
Loading