Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
10 changes: 9 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

> **Note**: odd version numbers, for example, `0.13.0`, are not included in this changelog. They are used to test the new features and fixes before the final release.

## [0.27.0] - Unreleased

### Added:

- Task provider: Added `devproxy` task provider to run Dev Proxy commands
- Problem watcher: Added `$devproxy-watch`
- Snippets: Added `devproxy-task-start` - Start Dev Proxy VS Code Task
- Snippets: Added `devproxy-task-stop` - Stop Dev Proxy VS Code Task

## [0.26.3] - 2025-06-27

### Fixed:
Expand Down Expand Up @@ -56,7 +65,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Snippets: Added `devproxy-plugin-openai-telemetry-config` - OpenAITelemetryPlugin config section
- Snippets: Added `devproxy-plugin-prices-file` - OpenAITelemetryPlugin telemetry prices file
- Snippets: Added `devproxy-plugin-price` - OpenAITelemetryPlugin telemetry model price
- Code

### Changed:

Expand Down
33 changes: 33 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,10 @@ Shown when the active document is a Dev Proxy configuration file
- New version detection
- Upgrade Dev Proxy

### Problem Watcher

- `$devproxy-watch` - Used for background tasks to tell VS Code when Dev Proxy has started

### Settings

- `dev-proxy-toolkit.version` - Determines the version to use when Dev Proxy and Dev Proxy Beta are installed side by side. Can be `stable` (default) or `beta`.
Expand Down Expand Up @@ -169,6 +173,8 @@ Shown when the active document is a Dev Proxy configuration file
| `devproxy-reporter-json` | JsonReporter instance |
| `devproxy-reporter-markdown` | MarkdownReporter instance |
| `devproxy-reporter-plain-text` | PlainTextReporter instance |
| `devproxy-task-start` | Start Dev Proxy VS Code Task |
| `devproxy-task-stop` | Stop Dev Proxy VS Code Task |

### Status Bar

Expand All @@ -178,3 +184,30 @@ Shown when the active document is a Dev Proxy configuration file
- Display radio tower when Dev Proxy is running
- Display error is Dev Proxy is not installed
- Upgrade Dev Proxy progress

### Task Provider

- Start Dev Proxy Task
- Stop Dev Proxy Task

Example `.vscode/tasks.json`:

```json
{
"version": "2.0.0",
"tasks": [
{
"label": "Start Dev Proxy",
"type": "devproxy",
"command": "start",
"isBackground": true,
"problemMatcher": "$devproxy-watch"
},
{
"label": "Stop Dev Proxy",
"type": "devproxy",
"command": "stop"
}
]
}
```
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

60 changes: 58 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "dev-proxy-toolkit",
"displayName": "Dev Proxy Toolkit",
"description": "Makes it easy to create and update Dev Proxy configuration files.",
"version": "0.26.3",
"version": "0.27.0",
"publisher": "garrytrinder",
"engines": {
"vscode": "^1.101.0"
Expand Down Expand Up @@ -131,6 +131,35 @@
}
]
},
"taskDefinitions": [
{
"type": "devproxy",
"required": [
"command"
],
"properties": {
"command": {
"type": "string",
"enum": [
"start",
"stop"
],
"description": "The Dev Proxy command to execute"
},
"configFile": {
"type": "string",
"description": "Path to the Dev Proxy configuration file"
},
"args": {
"type": "array",
"items": {
"type": "string"
},
"description": "Additional command-line arguments"
}
}
}
],
"snippets": [
{
"language": "json",
Expand Down Expand Up @@ -173,7 +202,34 @@
"description": "The port number used to communicate with Dev Proxy API."
}
}
}
},
"problemMatchers": [
{
"name": "devproxy-watch",
"label": "Dev Proxy Background Task",
"owner": "dev-proxy-toolkit",
"source": "Dev Proxy",
"fileLocation": "absolute",
"pattern": [
{
"regexp": "^\\[\\d{2}:\\d{2}:\\d{2}\\]\\s+(error|warn)\\s+(.*)$",
"severity": 1,
"message": 2
},
{
"regexp": "^\\s+at\\s+(.+):(\\d+):(\\d+)$",
"file": 1,
"line": 2,
"column": 3
}
],
"background": {
"activeOnStart": true,
"beginsPattern": "^.*Starting Dev Proxy.*$",
"endsPattern": "^.*(?:Dev Proxy is ready|Press CTRL\\+C to stop Dev Proxy).*$"
}
}
]
},
"preview": false,
"pricing": "Free",
Expand Down
2 changes: 2 additions & 0 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { registerCodeActions } from './codeactions';
import { updateGlobalState } from './state';
import { VersionPreference } from './enums';
import { registerMcpServer } from './mcp';
import { registerTaskProvider } from './taskprovider';

export const activate = async (context: vscode.ExtensionContext): Promise<vscode.ExtensionContext> => {

Expand All @@ -24,6 +25,7 @@ export const activate = async (context: vscode.ExtensionContext): Promise<vscode
registerCodeLens(context);
registerCommands(context, configuration);
registerMcpServer(context);
registerTaskProvider(context);

const notification = handleStartNotification(context);
processNotification(notification);
Expand Down
24 changes: 24 additions & 0 deletions src/snippets.json
Original file line number Diff line number Diff line change
Expand Up @@ -1086,5 +1086,29 @@
"}"
],
"description": "PlainTextReporter instance"
},
"StartTask": {
"prefix": "devproxy-task-start",
"body": [
"{",
"\t\"label\": \"Start Dev Proxy\",",
"\t\"type\": \"devproxy\",",
"\t\"command\": \"start\",",
"\t\"isBackground\": true,",
"\t\"problemMatcher\": \"\\$devproxy-watch\"",
"}"
],
"description": "Start Dev Proxy VS Code Task"
},
"StopTask": {
"prefix": "devproxy-task-stop",
"body": [
"{",
"\t\"label\": \"Stop Dev Proxy\",",
"\t\"type\": \"devproxy\",",
"\t\"command\": \"stop\"",
"}"
],
"description": "Stop Dev Proxy VS Code Task"
}
}
141 changes: 141 additions & 0 deletions src/taskprovider.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
import * as vscode from 'vscode';
import { getDevProxyExe } from './detect';
import { VersionPreference } from './enums';

interface DevProxyTaskDefinition extends vscode.TaskDefinition {
type: 'devproxy';
command: 'start' | 'stop';
configFile?: string;
args?: string[];
label?: string;
}

export class DevProxyTaskProvider implements vscode.TaskProvider {
static DevProxyType = 'devproxy';
private devProxyExe: string;

constructor(private context: vscode.ExtensionContext) {
const configuration = vscode.workspace.getConfiguration('dev-proxy-toolkit');
const versionPreference = configuration.get('version') as VersionPreference;
this.devProxyExe = getDevProxyExe(versionPreference);
}

provideTasks(): Thenable<vscode.Task[]> | undefined {
return this.getDevProxyTasks();
}

resolveTask(task: vscode.Task): vscode.Task | undefined {
const definition = task.definition as DevProxyTaskDefinition;

if (definition.type !== DevProxyTaskProvider.DevProxyType) {
return undefined;
}

return this.createTaskFromDefinition(definition);
}

private async getDevProxyTasks(): Promise<vscode.Task[]> {
const tasks: vscode.Task[] = [];

tasks.push(this.createStartTask());
tasks.push(this.createStopTask());

return tasks;
}

private createStartTask(): vscode.Task {
const definition: DevProxyTaskDefinition = {
type: 'devproxy',
command: 'start',
label: 'Start Dev Proxy'
};

return this.createTaskFromDefinition(definition);
}

private createStopTask(): vscode.Task {
const definition: DevProxyTaskDefinition = {
type: 'devproxy',
command: 'stop',
label: 'Stop Dev Proxy'
};

return this.createTaskFromDefinition(definition);
}

private createTaskFromDefinition(definition: DevProxyTaskDefinition): vscode.Task {
let execution: vscode.ShellExecution;

if (definition.command === 'start') {
const args = this.buildArgumentsFromDefinition(definition);
execution = new vscode.ShellExecution(this.devProxyExe, args, {
cwd: '${workspaceFolder}'
});
} else if (definition.command === 'stop') {
// Use curl to stop Dev Proxy via API
const configuration = vscode.workspace.getConfiguration('dev-proxy-toolkit');
const apiPort = configuration.get('apiPort', 8897);
execution = new vscode.ShellExecution('curl', [
'-X', 'POST',
`http://localhost:${apiPort}/proxy/stopproxy`
]);
} else {
throw new Error(`Unsupported command: ${definition.command}`);
}

const task = new vscode.Task(
definition,
vscode.TaskScope.Workspace,
definition.label || `Dev Proxy: ${definition.command}`,
DevProxyTaskProvider.DevProxyType,
execution,
definition.command === 'start' ? ['$devproxy-watch'] : []
);

// Configure task properties based on command
if (definition.command === 'start') {
task.group = vscode.TaskGroup.Build;
task.isBackground = true;
task.presentationOptions = {
echo: true,
reveal: vscode.TaskRevealKind.Always,
focus: false,
panel: vscode.TaskPanelKind.Dedicated,
showReuseMessage: true,
clear: false
};
} else if (definition.command === 'stop') {
task.group = vscode.TaskGroup.Build;
task.presentationOptions = {
echo: false,
reveal: vscode.TaskRevealKind.Silent,
focus: false
};
}

return task;
}

private buildArgumentsFromDefinition(definition: DevProxyTaskDefinition): string[] {
const args: string[] = [];

// Handle specific properties
if (definition.configFile) {
args.push('--config-file', definition.configFile);
}

// Add any additional args
if (definition.args) {
args.push(...definition.args);
}

return args;
}
}

export const registerTaskProvider = (context: vscode.ExtensionContext) => {
const provider = new DevProxyTaskProvider(context);
context.subscriptions.push(
vscode.tasks.registerTaskProvider(DevProxyTaskProvider.DevProxyType, provider)
);
};