Skip to content

Commit

Permalink
Apply automatic changes
Browse files Browse the repository at this point in the history
  • Loading branch information
jellydn authored and github-actions[bot] committed Oct 11, 2024
1 parent 505d4f2 commit 4d2d607
Show file tree
Hide file tree
Showing 4 changed files with 110 additions and 80 deletions.
16 changes: 4 additions & 12 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,7 @@
"version": "0.0.0",
"private": true,
"description": "Streamline API development in VSCode. Run Hurl requests, manage variables, and view responses directly in your editor.",
"categories": [
"Other"
],
"categories": ["Other"],
"homepage": "https://github.com/jellydn/vscode-hurl-runner#readme",
"bugs": {
"url": "https://github.com/jellydn/vscode-hurl-runner/issues"
Expand All @@ -20,11 +18,7 @@
"author": "Dung Huynh Duc <dung@productsway.com>",
"publisher": "jellydn",
"main": "./dist/index.js",
"files": [
"LICENSE.md",
"dist/*",
"res/*"
],
"files": ["LICENSE.md", "dist/*", "res/*"],
"scripts": {
"build": "tsup src/index.ts --external vscode",
"dev": "nr build --watch",
Expand Down Expand Up @@ -93,9 +87,7 @@
}
]
},
"activationEvents": [
"onStartupFinished"
],
"activationEvents": ["onStartupFinished"],
"devDependencies": {
"@biomejs/biome": "1.9.3",
"@types/node": "^22.7.5",
Expand All @@ -121,4 +113,4 @@
"dependencies": {
"nano-spawn": "^0.1.0"
}
}
}
68 changes: 39 additions & 29 deletions src/hurl-parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,14 @@ interface ParsedHurlOutput {
entries: ParsedEntry[];
}

function formatTimings(timings: Record<string, string>): Record<string, string> {
function formatTimings(
timings: Record<string, string>,
): Record<string, string> {
const formattedTimings: Record<string, string> = {};

for (const [key, value] of Object.entries(timings)) {
if (key !== 'begin' && key !== 'end') {
if (value.endsWith('µs')) {
if (key !== "begin" && key !== "end") {
if (value.endsWith("µs")) {
// Convert microseconds to a more readable format
const microseconds = Number.parseInt(value.slice(0, -3));
let formattedValue: string;
Expand All @@ -45,78 +47,86 @@ function formatTimings(timings: Record<string, string>): Record<string, string>
// A line starting with ‘>’ means data sent by Hurl.
// A line staring with ‘<’ means data received by Hurl.
// A line starting with ‘*’ means additional info provided by Hurl.
export function parseHurlOutput(stderr: string, stdout: string): ParsedHurlOutput {
const lines = stderr.split('\n');
export function parseHurlOutput(
stderr: string,
stdout: string,
): ParsedHurlOutput {
const lines = stderr.split("\n");
const entries: ParsedEntry[] = [];
let currentEntry: ParsedEntry | null = null;
let isResponseHeader = false;
let isTimings = false;

for (const line of lines) {
if (line.startsWith('* Executing entry')) {
if (line.startsWith("* Executing entry")) {
if (currentEntry) {
entries.push(currentEntry);
}
currentEntry = {
requestMethod: '',
requestUrl: '',
requestMethod: "",
requestUrl: "",
requestHeaders: {},
response: {
status: '',
status: "",
headers: {},
body: ''
body: "",
},
timings: {}
timings: {},
};
isResponseHeader = false;
isTimings = false;
} else if (line.startsWith('* Request:')) {
} else if (line.startsWith("* Request:")) {
const match = line.match(/\* Request:\s*\* (\w+) (.*)/);
if (match && currentEntry) {
currentEntry.requestMethod = match[1];
currentEntry.requestUrl = match[2];
}
} else if (line.startsWith('* curl')) {
} else if (line.startsWith("* curl")) {
if (currentEntry) {
currentEntry.curlCommand = line.slice(2).trim();
}
} else if (line.startsWith('> ')) {
if (line.startsWith('> GET ') || line.startsWith('> POST ') || line.startsWith('> PUT ') || line.startsWith('> DELETE ')) {
const [method, path] = line.slice(2).split(' ');
} else if (line.startsWith("> ")) {
if (
line.startsWith("> GET ") ||
line.startsWith("> POST ") ||
line.startsWith("> PUT ") ||
line.startsWith("> DELETE ")
) {
const [method, path] = line.slice(2).split(" ");
if (currentEntry) {
currentEntry.requestMethod = method;
currentEntry.requestUrl = path;
}
} else {
const [key, ...values] = line.slice(2).split(':');
const [key, ...values] = line.slice(2).split(":");
if (key && values.length && currentEntry) {
currentEntry.requestHeaders[key.trim()] = values.join(':').trim();
currentEntry.requestHeaders[key.trim()] = values.join(":").trim();
}
}
} else if (line.startsWith('< ')) {
} else if (line.startsWith("< ")) {
isResponseHeader = true;
if (line.startsWith('< HTTP/')) {
if (line.startsWith("< HTTP/")) {
if (currentEntry) {
currentEntry.response.status = line.slice(2);
}
} else {
const [key, ...values] = line.slice(2).split(':');
const [key, ...values] = line.slice(2).split(":");
if (key && values.length && currentEntry) {
currentEntry.response.headers[key.trim()] = values.join(':').trim();
currentEntry.response.headers[key.trim()] = values.join(":").trim();
}
}
} else if (line.startsWith('* Timings:')) {
} else if (line.startsWith("* Timings:")) {
isTimings = true;
} else if (isTimings && line.trim() !== '') {
} else if (isTimings && line.trim() !== "") {
// Remove the '* ' prefix if it exists
const cleanedLine = line.startsWith('* ') ? line.slice(2) : line;
const [key, value] = cleanedLine.split(':').map(s => s.trim());
if (currentEntry && key && value && key !== 'begin' && key !== 'end') {
const cleanedLine = line.startsWith("* ") ? line.slice(2) : line;
const [key, value] = cleanedLine.split(":").map((s) => s.trim());
if (currentEntry && key && value && key !== "begin" && key !== "end") {
if (currentEntry.timings) {
currentEntry.timings[key] = value;
}
}
} else if (isTimings && line.trim() === '') {
} else if (isTimings && line.trim() === "") {
isTimings = false;
if (currentEntry?.timings) {
currentEntry.timings = formatTimings(currentEntry.timings);
Expand All @@ -134,4 +144,4 @@ export function parseHurlOutput(stderr: string, stdout: string): ParsedHurlOutpu
}

return { entries };
}
}
90 changes: 59 additions & 31 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,10 @@ const { activate, deactivate } = defineExtension(() => {
resultPanel.reveal(vscode.ViewColumn.Two);
};

const showResultInWebView = (result: { stdout: string; stderr: string }, isError = false) => {
const showResultInWebView = (
result: { stdout: string; stderr: string },
isError = false,
) => {
responseLogger.clear();
responseLogger.info(`Stdout: ${result.stdout}`);
responseLogger.info(`Stderr: ${result.stderr}`);
Expand All @@ -64,41 +67,50 @@ const { activate, deactivate } = defineExtension(() => {
});
}

const title = isError ? 'Hurl Runner: Error' : 'Hurl Runner: Result';
const title = isError ? "Hurl Runner: Error" : "Hurl Runner: Result";

// Parse the output
const parsedOutput = parseHurlOutput(result.stderr, result.stdout);

// Create a formatted HTML output for each entry
const htmlOutput = parsedOutput.entries.map((entry, index) => {
let bodyType = 'text';
let formattedBody = entry.response.body || 'No response body';
if (formattedBody.trim().startsWith('{')) {
bodyType = 'json';
try {
formattedBody = JSON.stringify(JSON.parse(formattedBody), null, 2);
} catch {
// If parsing fails, leave it as is
const htmlOutput = parsedOutput.entries
.map((entry, index) => {
let bodyType = "text";
let formattedBody = entry.response.body || "No response body";
if (formattedBody.trim().startsWith("{")) {
bodyType = "json";
try {
formattedBody = JSON.stringify(JSON.parse(formattedBody), null, 2);
} catch {
// If parsing fails, leave it as is
}
} else if (formattedBody.trim().startsWith("<")) {
bodyType = formattedBody.trim().startsWith("<?xml") ? "xml" : "html";
}
} else if (formattedBody.trim().startsWith('<')) {
bodyType = formattedBody.trim().startsWith('<?xml') ? 'xml' : 'html';
}

return `
return `
<div class="entry">
<h3>Request</h3>
<pre><code class="language-http">${entry.requestMethod} ${entry.requestUrl}</code></pre>
<details>
<summary>Headers</summary>
<pre><code class="language-http">${Object.entries(entry.requestHeaders).map(([key, value]) => `${key}: ${value}`).join('\n')}</code></pre>
<pre><code class="language-http">${Object.entries(
entry.requestHeaders,
)
.map(([key, value]) => `${key}: ${value}`)
.join("\n")}</code></pre>
</details>
${entry.curlCommand ? `
${
entry.curlCommand
? `
<details>
<summary>cURL Command</summary>
<pre><code class="language-bash">${entry.curlCommand}</code></pre>
</details>
` : ''}
`
: ""
}
<h3>Response Body</h3>
<pre class="response-body"><code class="language-${bodyType}">${formattedBody}</code></pre>
Expand All @@ -107,18 +119,29 @@ const { activate, deactivate } = defineExtension(() => {
<summary>Response Details</summary>
<p>Status: ${entry.response.status}</p>
<h4>Headers</h4>
<pre><code class="language-http">${Object.entries(entry.response.headers).map(([key, value]) => `${key}: ${value}`).join('\n')}</code></pre>
<pre><code class="language-http">${Object.entries(
entry.response.headers,
)
.map(([key, value]) => `${key}: ${value}`)
.join("\n")}</code></pre>
</details>
${entry.timings ? `
${
entry.timings
? `
<details>
<summary>Timings</summary>
<pre><code class="language-yaml">${Object.entries(entry.timings).map(([key, value]) => `${key}: ${value}`).join('\n')}</code></pre>
<pre><code class="language-yaml">${Object.entries(entry.timings)
.map(([key, value]) => `${key}: ${value}`)
.join("\n")}</code></pre>
</details>
` : ''}
`
: ""
}
</div>
`;
}).join('<hr>');
})
.join("<hr>");

resultPanel.webview.html = `
<!DOCTYPE html>
Expand Down Expand Up @@ -154,7 +177,7 @@ const { activate, deactivate } = defineExtension(() => {
async () => {
const editor = vscode.window.activeTextEditor;
if (!editor) {
showResultInWebView({ stdout: '', stderr: "No active editor" }, true);
showResultInWebView({ stdout: "", stderr: "No active editor" }, true);
return;
}

Expand All @@ -167,7 +190,10 @@ const { activate, deactivate } = defineExtension(() => {
try {
const entry = findEntryAtLine(fileContent, currentLine);
if (!entry) {
showResultInWebView({ stdout: '', stderr: "No Hurl entry found at the current line" }, true);
showResultInWebView(
{ stdout: "", stderr: "No Hurl entry found at the current line" },
true,
);
return;
}

Expand All @@ -184,8 +210,9 @@ const { activate, deactivate } = defineExtension(() => {

showResultInWebView(result);
} catch (error) {
const errorMessage = error instanceof Error ? error.message : "Unknown error";
showResultInWebView({ stdout: '', stderr: errorMessage }, true);
const errorMessage =
error instanceof Error ? error.message : "Unknown error";
showResultInWebView({ stdout: "", stderr: errorMessage }, true);
}
},
);
Expand All @@ -195,7 +222,7 @@ const { activate, deactivate } = defineExtension(() => {
async () => {
const editor = vscode.window.activeTextEditor;
if (!editor) {
showResultInWebView({ stdout: '', stderr: "No active editor" }, true);
showResultInWebView({ stdout: "", stderr: "No active editor" }, true);
return;
}

Expand All @@ -210,8 +237,9 @@ const { activate, deactivate } = defineExtension(() => {

showResultInWebView(result);
} catch (error) {
const errorMessage = error instanceof Error ? error.message : "Unknown error";
showResultInWebView({ stdout: '', stderr: errorMessage }, true);
const errorMessage =
error instanceof Error ? error.message : "Unknown error";
showResultInWebView({ stdout: "", stderr: errorMessage }, true);
}
},
);
Expand Down Expand Up @@ -257,4 +285,4 @@ const { activate, deactivate } = defineExtension(() => {
};
});

export { activate, deactivate };
export { activate, deactivate };
Loading

0 comments on commit 4d2d607

Please sign in to comment.