Skip to content

Commit

Permalink
VSCode Plugin initial implementation (#5930)
Browse files Browse the repository at this point in the history
  • Loading branch information
hsubox76 committed Jun 9, 2023
1 parent ab04554 commit 628aa75
Show file tree
Hide file tree
Showing 71 changed files with 13,529 additions and 1 deletion.
2 changes: 2 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -128,5 +128,7 @@ module.exports = {
"/src/frameworks/docs/**",
// This file is taking a very long time to lint, 2-4m
"src/emulator/auth/schema.ts",
// TODO(hsubox76): Set up a job to run eslint separately on vscode dir
"firebase-vscode/",
],
};
24 changes: 24 additions & 0 deletions firebase-vscode/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"root": true,
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaVersion": 6,
"sourceType": "module"
},
"plugins": [
"@typescript-eslint"
// "react"
],
"rules": {
"@typescript-eslint/semi": "warn",
"curly": "warn",
"eqeqeq": "warn",
"no-throw-literal": "warn",
"semi": "off"
},
"ignorePatterns": [
"out",
"dist",
"**/*.d.ts"
]
}
4 changes: 4 additions & 0 deletions firebase-vscode/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
*.vsix
dist/
*.scss.d.ts
resources/dist
3 changes: 3 additions & 0 deletions firebase-vscode/.prettierrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module.exports = {
printWidth: 80,
};
7 changes: 7 additions & 0 deletions firebase-vscode/.vscode/extensions.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
// See http://go.microsoft.com/fwlink/?LinkId=827846
// for the documentation about the extensions.json format
"recommendations": [
"dbaeumer.vscode-eslint"
]
}
34 changes: 34 additions & 0 deletions firebase-vscode/.vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// A launch configuration that compiles the extension and then opens it inside a new window
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
{
"version": "0.2.0",
"configurations": [
{
"name": "Run Extension",
"type": "extensionHost",
"request": "launch",
"args": [
"--extensionDevelopmentPath=${workspaceFolder}"
],
"outFiles": [
"${workspaceFolder}/dist/**/*.js"
],
"preLaunchTask": "${defaultBuildTask}"
},
{
"name": "Extension Tests",
"type": "extensionHost",
"request": "launch",
"args": [
"--extensionDevelopmentPath=${workspaceFolder}",
"--extensionTestsPath=${workspaceFolder}/dist/test/suite/index"
],
"outFiles": [
"${workspaceFolder}/dist/test/**/*.js"
],
"preLaunchTask": "${defaultBuildTask}"
}
]
}
11 changes: 11 additions & 0 deletions firebase-vscode/.vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// Place your settings in this file to overwrite default and user settings.
{
"files.exclude": {
"dist": false // set this to true to hide the "out" folder with the compiled JS files
},
"search.exclude": {
"dist": true // set this to false to include "out" folder in search results
},
// Turn off tsc task auto detection since we have the necessary tasks as npm scripts
"typescript.tsc.autoDetect": "off"
}
20 changes: 20 additions & 0 deletions firebase-vscode/.vscode/tasks.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
{
"version": "2.0.0",
"tasks": [
{
"type": "npm",
"script": "watch",
"problemMatcher": ["$tsc-watch", "$ts-webpack-watch"],
"isBackground": true,
"presentation": {
"reveal": "always"
},
"group": {
"kind": "build",
"isDefault": true
}
}
]
}
18 changes: 18 additions & 0 deletions firebase-vscode/.vscodeignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
.vscode/**
.vscode-test/**
src/**
webviews/**
common/**
extension/**
public/**
.gitignore
.yarnrc
vsc-extension-quickstart.md
**/tsconfig.json
**/.eslintrc.json
**/*.map
**/*.ts
*.vsix
webpack.*.js
../
*.zip
9 changes: 9 additions & 0 deletions firebase-vscode/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Change Log

All notable changes to the "firebase-vscode" extension will be documented in this file.

Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how to structure this file.

## [Unreleased]

- Initial release
21 changes: 21 additions & 0 deletions firebase-vscode/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
The MIT License (MIT)

Copyright (c) 2023 Firebase

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
64 changes: 64 additions & 0 deletions firebase-vscode/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# firebase-vscode README

This extension is in the development and exploration stage.

## Running

1. In order to make sure f5 launches the extension properly, first open your
VS Code session from the `firebase-vscode` subdirectory (not the `firebase-tools` directory).
2. npm i
3. f5 to run opens new window
f5 -> npm run watch defined in tasks.json
My terminal didn't have npm available but yours might

Workaround if f5 doesnt work:

1. Execute `npm run watch` from within the vscode directory
Aside: Running `npm run watch` or `npm run build` the extension is compiled into dist (extension.js)
Changing code within extension is hot-reloaded
Modifying extensions.js will not hot-reload
source file src/extension.ts
2. Wait for completion
3. Hit play from the left nav

New code changes are automatically rebuilt if you have `watch` running, however the new VSCode Plugin-enabled window will not reflect changes until reloaded.
Manual reload from new window: "Developer: Reload Window" Default hotkey: cmd + R

The communication between UI and extension done via the broker (see webview.postMessage)
Web view uses react (carry-over from the hackweek project courtesy of Roman and Prakhar)

## Structure

Extention.ts main entry point, calls sidebar.ts and workflow.ts
sidebar.ts loads the UI from the webviews folder
workflow.ts is the driving component (logic source)
cli.ts wraps CLI methods, importing from firebase-tools/src

When workflow.ts needs to execute some CLI command, it defers to cli.ts

## State

currentOptions maintains the currentState of the plugin and is passed as a whole object to populate calls to the firebase-tools methods
`prepare` in the command includes a lot of

## Logic

Calling firebase-tools in general follows the stuff:

1. instead of calling `before`, call `requireAuth` instead
requireAuth is a prerequisite for the plugin UI, needed
Zero-state (before login) directs the user to sign in with google (using firebase-tools CLI)
2. prepare is an implicit command in the cmd class
3. action

requireAuth -> login with service account or check that you're already logged in via firebase-tools

## Open issues

Login changes in the CLI are not immediately reflected in the Plugin, requires restart
If logged-out in the middle of a plugin session, handle requireAuth errors gracefully
Plugin startup is flaky sometimes
Unit/Integration tests are not developed
Code cleanliness/structure TODOs
tsconfig.json's rootDirs includes ["src", "../src", "common"] which causes some issues with import autocomplete
Three package.jsons - one for monospace and one for the standalone plugin, and then root to copy the correct version
2 changes: 2 additions & 0 deletions firebase-vscode/common/firebaserc.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
import { RCData } from '../../src/rc';
export interface FirebaseRC extends Partial<RCData> {}
87 changes: 87 additions & 0 deletions firebase-vscode/common/messaging/broker.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import { MessageParamsMap } from "./protocol";
import { Listener, Message, MessageListeners } from "./types";
import { Webview } from "vscode";

const isObject = (val: any): boolean => typeof val === "object" && val !== null;

type Receiver = {} | Webview;

export abstract class Broker<
OutgoingMessages extends MessageParamsMap,
IncomingMessages extends MessageParamsMap,
R extends Receiver
> {
protected readonly listeners: MessageListeners<IncomingMessages> = {};

abstract sendMessage<T extends keyof OutgoingMessages>(message: T, data: OutgoingMessages[T]): void;
registerReceiver(receiver: R): void { }

addListener(message: string, cb: Listener<IncomingMessages>): void {
if (!this.listeners[message]) {
this.listeners[message] = { listeners: [] };
}
this.listeners[message].listeners.push(cb);
}

executeListeners(message: Message<IncomingMessages>) {
if (message === undefined || !isObject(message) || !message.command) {
return;
}

const d = message;

if (this.listeners[d.command] === undefined) {
return;
}

for (const listener of this.listeners[d.command].listeners) {
d.data === undefined ? listener() : listener(d.data);
};
}

delete(): void { }
}

export interface BrokerImpl<
OutgoingMessages,
IncomingMessages,
R extends Receiver
> {
send<E extends keyof OutgoingMessages>(
message: E,
args?: OutgoingMessages[E]
): void;
registerReceiver(receiver: R): void;
on<E extends keyof IncomingMessages>(
message: Extract<E, string>,
listener: (params: IncomingMessages[E]) => void
): void;
delete(): void;
}

export function createBroker<
OutgoingMessages extends MessageParamsMap,
IncomingMessages extends MessageParamsMap,
R extends Receiver
>(broker: Broker<OutgoingMessages, IncomingMessages, R>): BrokerImpl<OutgoingMessages, IncomingMessages, Receiver> {
return {
send<E extends keyof OutgoingMessages>(
message: Extract<E, string>,
args?: OutgoingMessages[E]
): void {
broker.sendMessage(message, args);
},
registerReceiver(receiver: R): void {
broker.registerReceiver(receiver);
},
on<E extends keyof IncomingMessages>(
message: Extract<E, string>,
listener: (params: IncomingMessages[E]) => void
): void {
broker.addListener(message, listener);
},
delete(): void {
broker.delete();
}
};
}
Loading

0 comments on commit 628aa75

Please sign in to comment.