Skip to content

Commit

Permalink
Add proxy installation check (#42)
Browse files Browse the repository at this point in the history
  • Loading branch information
garrytrinder authored Feb 13, 2024
1 parent d7d1b22 commit f84c066
Show file tree
Hide file tree
Showing 10 changed files with 376 additions and 193 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"Testing"
],
"activationEvents": [
"onLanguage:json"
"onStartupFinished"
],
"repository": {
"type": "git",
Expand Down
11 changes: 10 additions & 1 deletion src/codelens.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,16 @@
import * as vscode from 'vscode';
import {isConfigFile, getASTNode, getRangeFromASTNode} from './helpers';
import { isConfigFile, getASTNode, getRangeFromASTNode } from './helpers';
import parse from 'json-to-ast';

export const registerCodeLens = (context: vscode.ExtensionContext) => {
context.subscriptions.push(
vscode.languages.registerCodeLensProvider(
{ scheme: 'file', language: 'json' },
pluginLensProvider
)
);
};

export const pluginLensProvider: vscode.CodeLensProvider = {
provideCodeLenses(
document: vscode.TextDocument,
Expand Down
20 changes: 20 additions & 0 deletions src/commands.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import * as vscode from 'vscode';
import { pluginDocs } from './constants';

export const registerCommands = (context: vscode.ExtensionContext) => {
context.subscriptions.push(
vscode.commands.registerCommand('dev-proxy-toolkit.install', async (platform: NodeJS.Platform) => {
const url = `https://aka.ms/devproxy/install/${platform === 'darwin' ? 'macos' : 'windows'}`;
vscode.env.openExternal(vscode.Uri.parse(url));
}));

context.subscriptions.push(
vscode.commands.registerCommand(
'dev-proxy-toolkit.openPluginDoc',
pluginName => {
const target = vscode.Uri.parse(pluginDocs[pluginName].url);
vscode.env.openExternal(target);
}
)
);
};
72 changes: 72 additions & 0 deletions src/detect.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import { exec } from 'child_process';
import { DevProxyInstall } from './types';
import os from 'os';

const getExecutablePath = async (filename: string): Promise<string> => {
const command = getFindCommand();
if (command === '') {
return '';
}

try {
return await executeCommand(`${command} ${filename}`);
} catch (error) {
console.error(error);
return '';
}
};

const getFindCommand = () => {
const platform = os.platform();
let command = '';
if (platform === 'win32') {
command = 'pwsh.exe -c "where.exe devproxy"';
}
if (platform === 'darwin') {
command = '$SHELL -c "which devproxy"';
}
return command;
};

const getVersion = async (filePath: string) => {
if (filePath === '') {
return '';
}
try {
const version = await executeCommand(`${filePath.trim()} --version`);
return version.trim();
} catch (error) {
console.error(error);
return "";
}
};

export const executeCommand = async (cmd: string): Promise<string> => {
return new Promise((resolve, reject) => {
exec(cmd, (error, stdout, stderr) => {
if (error) {
reject(`exec error: ${error}`);
} else if (stderr) {
reject(`stderr: ${stderr}`);
} else {
resolve(stdout);
}
});
});
};

export const detectDevProxyInstall = async (): Promise<DevProxyInstall> => {
const filePath = await getExecutablePath('devproxy');
const version = await getVersion(filePath);
const isInstalled = filePath !== '';
const isBeta = version.includes('beta');
const platform = os.platform();

return {
filePath,
version,
isInstalled,
isBeta,
platform
};
};
124 changes: 124 additions & 0 deletions src/diagnostics.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
import * as vscode from 'vscode';
import parse from "json-to-ast";
import { pluginSnippets } from "./constants";
import { getASTNode, getRangeFromASTNode } from "./helpers";

export const updateDiagnostics = (
document: vscode.TextDocument,
collection: vscode.DiagnosticCollection
): void => {
let diagnostics: vscode.Diagnostic[] = [];

const documentNode = parse(document.getText()) as parse.ObjectNode;

// check if urlsToWatch is empty
const urlsToWatchNode = getASTNode(
documentNode.children,
'Identifier',
'urlsToWatch'
);
if (
urlsToWatchNode &&
(urlsToWatchNode.value as parse.ArrayNode).children.length === 0
) {
diagnostics.push(
new vscode.Diagnostic(
getRangeFromASTNode(urlsToWatchNode),
'Add at least one url to watch.',
vscode.DiagnosticSeverity.Error
)
);
}

// check validity of plugins
const pluginsNode = getASTNode(
documentNode.children,
'Identifier',
'plugins'
);
if (
pluginsNode &&
(pluginsNode.value as parse.ArrayNode).children.length !== 0
) {
const pluginNodes = (pluginsNode.value as parse.ArrayNode)
.children as parse.ObjectNode[];

// check for plugins
if (pluginNodes.length === 0) {
diagnostics.push(
new vscode.Diagnostic(
getRangeFromASTNode(pluginsNode),
'Add at least one plugin',
vscode.DiagnosticSeverity.Error
)
);
}

// does the plugin have a config section?
pluginNodes.forEach((pluginNode: parse.ObjectNode) => {
const pluginNameNode = getASTNode(
pluginNode.children,
'Identifier',
'name'
);
const pluginName = (pluginNameNode?.value as parse.LiteralNode)
.value as string;
const enabledNode = getASTNode(
pluginNode.children,
'Identifier',
'enabled'
);
const isEnabled = (enabledNode?.value as parse.LiteralNode)
.value as boolean;
const pluginSnippet = pluginSnippets[pluginName];
const requiresConfig = pluginSnippet.config
? pluginSnippet.config.required
: false;

if (requiresConfig) {
// check to see if the plugin has a config section
const configSectionNode = getASTNode(
pluginNode.children,
'Identifier',
'configSection'
);
if (!configSectionNode) {
// there is no config section defined on the plugin instance
diagnostics.push(
new vscode.Diagnostic(
getRangeFromASTNode(pluginNode),
`${pluginName} requires a config section.`,
isEnabled
? vscode.DiagnosticSeverity.Error
: vscode.DiagnosticSeverity.Warning
)
);
} else {
// check to see if the config section is in the document
const configSectionName = (
configSectionNode.value as parse.LiteralNode
).value as string;
const configSection = getASTNode(
documentNode.children,
'Identifier',
configSectionName
);

if (!configSection) {
diagnostics.push(
new vscode.Diagnostic(
getRangeFromASTNode(configSectionNode.value),
`${configSectionName} config section is missing. Use '${pluginSnippet.config?.name}' snippet to create one.`,
isEnabled
? vscode.DiagnosticSeverity.Error
: vscode.DiagnosticSeverity.Warning
)
);
}
}
}
});
}

collection.set(document.uri, diagnostics);
};
24 changes: 24 additions & 0 deletions src/documents.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import * as vscode from 'vscode';
import { isConfigFile } from './helpers';
import { updateDiagnostics } from './diagnostics';

export const registerDocumentListeners = (context: vscode.ExtensionContext, collection: vscode.DiagnosticCollection) => {
context.subscriptions.push(
vscode.workspace.onDidOpenTextDocument(document => {
if (!isConfigFile(document)) {
return;
}
updateDiagnostics(document, collection);
})
);

context.subscriptions.push(
vscode.workspace.onDidChangeTextDocument(event => {
if (!isConfigFile(event.document)) {
collection.delete(event.document.uri);
return;
}
updateDiagnostics(event.document, collection);
})
);
};
Loading

0 comments on commit f84c066

Please sign in to comment.