Skip to content

Commit

Permalink
feat: add live reload + launch config for vscode extension (#1468)
Browse files Browse the repository at this point in the history
Also added new commands to run extension.

- `pnpm dev:vscode` - dev mode for VSCode extension
- `pnpm dev:language-server` - dev mode for Language Server
- `pnpm dev:all` - dev mode for all packages
- `pnpm dev:playground` - Force rebuild the playground frontend

You can now also press play on VSCode debugger for Launch VS Code
extension and it will run all the scripts for you to have live reload
and debuggin for the vscode extension
<!-- ELLIPSIS_HIDDEN -->


----

> [!IMPORTANT]
> Adds live reload and debugging for VSCode extension with new commands
and updates to configuration and documentation.
> 
>   - **Behavior**:
> - Adds live reload and debugging for VSCode extension using
`launch.json` and `tasks.json`.
> - New commands in `package.json`: `dev:vscode`, `dev:language-server`,
`dev:all`, `dev:playground`.
> - Updates `WebPanelView` in `WebPanelView.ts` to load scripts
differently in dev mode.
>   - **Configuration**:
>     - Adds `Watch All` and `Terminate All` tasks in `tasks.json`.
> - Modifies `launch.json` to include `preLaunchTask` and
`postDebugTask`.
>   - **Documentation**:
>     - Updates `README.md` with new development commands and workflows.
>   - **Build**:
> - Updates `vite.config.ts` to configure dev server and HMR for VSCode
webviews.
> 
> <sup>This description was created by </sup>[<img alt="Ellipsis"
src="https://img.shields.io/badge/Ellipsis-blue?color=175173">](https://www.ellipsis.dev?ref=BoundaryML%2Fbaml&utm_source=github&utm_medium=referral)<sup>
for c38da23. It will automatically
update as commits are pushed.</sup>


<!-- ELLIPSIS_HIDDEN -->
  • Loading branch information
seawatts authored Feb 17, 2025
1 parent 06a311b commit 4a38455
Show file tree
Hide file tree
Showing 7 changed files with 216 additions and 16 deletions.
4 changes: 3 additions & 1 deletion typescript/.vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@
],
"env": {
"VSCODE_DEBUG_MODE": "true"
}
},
"preLaunchTask": "Watch All",
"postDebugTask": "Terminate All"
},
{
"type": "node",
Expand Down
63 changes: 63 additions & 0 deletions typescript/.vscode/tasks.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "Watch All",
"dependsOn": ["Watch Web Panel", "Watch VSCode Extension"],
"group": {
"kind": "build",
"isDefault": true
}
},
{
"label": "Terminate All",
"command": "echo ${input:terminate}",
"type": "shell",
"problemMatcher": []
},
{
"label": "Watch Web Panel",
"type": "shell",
"command": "cd ${workspaceFolder}/vscode-ext/packages/web-panel && pnpm run watch",
"isBackground": true,
"problemMatcher": {
"pattern": {
"regexp": "."
},
"background": {
"activeOnStart": true,
"beginsPattern": "^.*VITE.*Dev server running at:",
"endsPattern": "^.*ready in.*$"
}
},
"presentation": {
"reveal": "always",
"panel": "new"
}
},
{
"label": "Watch VSCode Extension",
"type": "shell",
"command": "cd ${workspaceFolder}/vscode-ext/packages/vscode && pnpm run watch",
"isBackground": true,
"problemMatcher": {
"pattern": {
"regexp": "."
},
"background": {
"activeOnStart": true,
"beginsPattern": ".",
"endsPattern": "."
}
}
}
],
"inputs": [
{
"id": "terminate",
"type": "command",
"command": "workbench.action.tasks.terminate",
"args": "terminateAll"
}
]
}
98 changes: 97 additions & 1 deletion typescript/README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,63 @@
# BAML TypeScript Packages

This directory contains all TypeScript-related packages for BAML, including the VSCode extension, language server, and other utilities.

## Package Structure

- `vscode-ext/packages/vscode` - VSCode extension (package: `baml-client`)
- `vscode-ext/packages/language-server` - Language server (package: `@gloo-ai/baml-language-server`)
- `common` - Shared utilities and types
- `playground-common` - Shared code for the BAML playground
- `fiddle-frontend` - Frontend for the BAML playground
- Other utility packages for WASM bindings and CodeMirror integration

## Development

### Prerequisites

- Node.js (LTS version recommended)
- pnpm (package manager)

### Setup

1. Install dependencies:
```bash
pnpm install
```

2. Build all packages:
```bash
pnpm build
```

### Development Commands

Available scripts in package.json:
- `pnpm dev:vscode` - dev mode for VSCode extension
- `pnpm dev:language-server` - dev mode for Language Server
- `pnpm dev:all` - dev mode for all packages
- `pnpm dev:playground` - Force rebuild the playground frontend

### VSCode Extension Development

The VSCode extension is located in `vscode-ext/packages/vscode`. To develop:

1. Open the project in VSCode
2. Run `pnpm dev:vscode` to start the dev mode
3. Press F5 to launch a new VSCode instance with the extension

### Playground Development

The playground consists of multiple packages:

- `fiddle-frontend` - Next.js frontend
- `playground-common` - Shared utilities

To develop the playground:

1. Run `pnpm dev` to start all development servers
2. For frontend only, use `pnpm dev:playground`

# BAML TypeScript

> **⚠️ IMPORTANT NOTE**
Expand All @@ -10,7 +70,7 @@

To test the BAML playground in VSCode:

1. First, open the `root-wasm32.code-workspace` file in VSCode
1. First, open the [`root-wasm32.code-workspace`](../root-wasm32.code-workspace) file in VSCode
2. Press F5 or use the Run and Debug view
3. Select "Launch VS Code extension" from the debug configurations
4. A new VSCode window will open with the BAML extension running in development mode
Expand All @@ -22,3 +82,39 @@ You can also run both the VSCode extension and Language Server together by:
This will launch both the extension and attach the debugger to the language server.

> **Note**: Opening the workspace file is important as it contains the necessary VSCode settings and recommended extensions for development.
## Development Workflows

Here are the common development workflows depending on what you're working on:

### VSCode Extension Development

#### Client-side Only Changes (No Language Server)
If you're only making changes to the VSCode extension client-side:
```bash
pnpm dev:vscode
```

#### Language Server Only Changes
If you're working on the language server:
```bash
pnpm dev:language-server
```

#### Both Client and Language Server
If you're working on both components simultaneously, run the dev commands in separate terminals:
```bash
# Terminal 1 - VSCode Extension
pnpm dev:vscode

# Terminal 2 - Language Server
pnpm dev:language-server
```

### Rust Changes for Playground
When making changes to the Rust compiler that affect the playground:
```bash
# Rebuild the playground frontend
npx turbo build --force --filter=fiddle-frontend
```
Run this command after each compiler change, then relaunch the prompt fiddle to see your changes.
4 changes: 4 additions & 0 deletions typescript/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,12 @@
"scripts": {
"clean": "turbo clean",
"build": "pnpm i && turbo run build",
"build:playground": "turbo build --force --filter=fiddle-frontend",
"cache": "turbo cache list",
"dev": "turbo run dev",
"dev:vscode": "turbo run watch --filter=baml-client",
"dev:language-server": "turbo run watch --filter=@gloo-ai/baml-language-server",
"dev:playground": "turbo run dev --filter=fiddle-frontend",
"format": "biome format --write .",
"generate": "turbo run generate",
"lint": "turbo run lint",
Expand Down
39 changes: 27 additions & 12 deletions typescript/vscode-ext/packages/vscode/src/panels/WebPanelView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ import {

import { type Config, adjectives, animals, colors, uniqueNamesGenerator } from 'unique-names-generator'
import { URI } from 'vscode-uri'
import { getCurrentOpenedFile } from '../helpers/get-open-file'
import { bamlConfig, requestDiagnostics } from '../plugins/language-server'
import TelemetryReporter from '../telemetryReporter'
import { getCurrentOpenedFile } from '../helpers/get-open-file'

const customConfig: Config = {
dictionaries: [adjectives, colors, animals],
Expand Down Expand Up @@ -153,29 +153,44 @@ export class WebPanelView {
* rendered within the webview panel
*/
private _getWebviewContent(webview: Webview, extensionUri: Uri) {
// The CSS file from the React dist output
const stylesUri = getUri(webview, extensionUri, ['web-panel', 'dist', 'assets', 'index.css'])
// The JS file from the React dist output
const scriptUri = getUri(webview, extensionUri, ['web-panel', 'dist', 'assets', 'index.js'])

const isDevelopment = process.env.VSCODE_DEBUG_MODE === 'true'
const nonce = getNonce()

// Tip: Install the es6-string-html VS Code extension to enable code highlighting below
return /*html*/ `
const getBaseHtml = (scripts: string) => /*html*/ `
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" type="text/css" href="${stylesUri}">
<title>Hello World</title>
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; style-src ${webview.cspSource} 'unsafe-inline'; script-src 'nonce-${nonce}' 'unsafe-eval' http://localhost:* ws://localhost:*; connect-src ws://localhost:* http://localhost:*; img-src ${webview.cspSource} https:; font-src ${webview.cspSource};">
<title>BAML Playground</title>
${isDevelopment ? '' : `<link rel="stylesheet" type="text/css" href="${getUri(webview, extensionUri, ['web-panel', 'dist', 'assets', 'index.css'])}">`}
</head>
<body>
<div id="root">Waiting for react: ${scriptUri}</div>
<script type="module" nonce="${nonce}" src="${scriptUri}"></script>
<div id="root"></div>
${scripts}
</body>
</html>
`

if (isDevelopment) {
const devServerPort = process.env.VITE_PORT || '3000'
return getBaseHtml(/*html*/ `
<script type="module" nonce="${nonce}">
import RefreshRuntime from "http://localhost:${devServerPort}/@react-refresh"
RefreshRuntime.injectIntoGlobalHook(window)
window.$RefreshReg$ = () => {}
window.$RefreshSig$ = () => (type) => type
window.__vite_plugin_react_preamble_installed__ = true
</script>
<script type="module" nonce="${nonce}" src="http://localhost:${devServerPort}/@vite/client"></script>
<script type="module" nonce="${nonce}" src="http://localhost:${devServerPort}/src/main.tsx"></script>
`)
}

return getBaseHtml(/*html*/ `
<script type="module" nonce="${nonce}" src="${getUri(webview, extensionUri, ['web-panel', 'dist', 'assets', 'index.js'])}"></script>
`)
}

/**
Expand Down
2 changes: 1 addition & 1 deletion typescript/vscode-ext/packages/web-panel/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"build": "npx tsc --noEmit && vite build",
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
"preview": "NODE_ENV=development vite preview",
"watch": "NODE_ENV=development vite build --watch"
"watch": "NODE_ENV=development vite"
},
"dependencies": {
"@baml/common": "workspace:^",
Expand Down
22 changes: 21 additions & 1 deletion typescript/vscode-ext/packages/web-panel/vite.config.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import path from 'path'
import * as path from 'path'
import react from '@vitejs/plugin-react'
import { defineConfig } from 'vite'
import topLevelAwait from 'vite-plugin-top-level-await'
Expand All @@ -16,6 +16,19 @@ export default defineConfig({
wasm(),
topLevelAwait(),
],
server: {
port: process.env.VITE_PORT ? parseInt(process.env.VITE_PORT) : 3000,
strictPort: false, // Allow fallback to next available port
hmr: {
// This is needed for HMR to work in VSCode webviews
protocol: 'ws',
host: 'localhost',
},
watch: {
usePolling: true,
interval: 100,
},
},
resolve: {
alias: {
'@': path.resolve(__dirname, './src'),
Expand All @@ -26,16 +39,23 @@ export default defineConfig({
},
mode: isWatchMode ? 'development' : 'production',
build: {
target: 'esnext',
minify: isWatchMode ? false : 'esbuild',
outDir: 'dist',
sourcemap: isWatchMode ? 'inline' : false,
rollupOptions: {
external: ['baml_wasm_web/rpc'],
output: {
format: 'es',
entryFileNames: `assets/[name].js`,
chunkFileNames: `assets/[name].js`,
assetFileNames: `assets/[name].[ext]`,
},
},
},
optimizeDeps: {
esbuildOptions: {
target: 'esnext',
},
},
})

0 comments on commit 4a38455

Please sign in to comment.