diff --git a/dev/test-powershell-share.html b/dev/test-powershell-share.html new file mode 100644 index 0000000..64bfc7b --- /dev/null +++ b/dev/test-powershell-share.html @@ -0,0 +1,155 @@ + + +
+ + +This page tests the new PowerShell share format with multi-line query and sparql-generated output file.
+ + + + + + + + + + diff --git a/packages/yasqe/src/__tests__/share-test.ts b/packages/yasqe/src/__tests__/share-test.ts index 1ff2ce4..c8d17d8 100644 --- a/packages/yasqe/src/__tests__/share-test.ts +++ b/packages/yasqe/src/__tests__/share-test.ts @@ -105,7 +105,7 @@ describe("Share Functionality", () => { " }", ' ContentType = "application/x-www-form-urlencoded"', ' Body = "query=SELECT"', - ' OutFile = "result.json"', + ' OutFile = "sparql-generated.json"', "}", "", "Invoke-WebRequest @params", @@ -117,6 +117,37 @@ describe("Share Functionality", () => { expect(psString).to.include("Headers"); expect(psString).to.include("OutFile"); expect(psString).to.include("Accept"); + expect(psString).to.include("sparql-generated"); + }); + + it("should format PowerShell commands with here-string for query", () => { + const query = "SELECT * WHERE { ?s ?p ?o }"; + const lines = [ + '$query = @"', + query, + '"@', + "", + "$params = @{", + ' Uri = "https://example.com/sparql"', + ' Method = "Post"', + " Headers = @{", + ' "Accept" = "application/sparql-results+json"', + " }", + ' ContentType = "application/x-www-form-urlencoded"', + ' Body = "query=$([System.Net.WebUtility]::UrlEncode($query))"', + ' OutFile = "sparql-generated.json"', + "}", + "", + "Invoke-WebRequest @params", + ]; + const psString = lines.join("\n"); + + expect(psString).to.include('$query = @"'); + expect(psString).to.include('"@'); + expect(psString).to.include(query); + expect(psString).to.include('Body = "query=$([System.Net.WebUtility]::UrlEncode($query))"'); + expect(psString).to.not.include('Body = "query=`$query"'); // Should NOT escape the variable + expect(psString).to.include("sparql-generated"); }); it("should format wget commands with proper line breaks", () => { diff --git a/packages/yasqe/src/sparql.ts b/packages/yasqe/src/sparql.ts index 13a6513..6ac7e60 100644 --- a/packages/yasqe/src/sparql.ts +++ b/packages/yasqe/src/sparql.ts @@ -520,10 +520,48 @@ export function getAsPowerShellString(yasqe: Yasqe, _config?: Config["requestCon lines.push(headersLines.join("\n")); lines.push(" }"); } - lines.push(` OutFile = "result.${fileExtension}"`); + lines.push(` OutFile = "sparql-generated.${fileExtension}"`); lines.push("}"); } else if (ajaxConfig.reqMethod === "POST") { - const body = queryString.stringify(ajaxConfig.args); + // Extract the query/update parameter and other parameters separately + // Determine the query parameter name first (query takes precedence over update) + const queryParamName = ajaxConfig.args.query !== undefined ? "query" : "update"; + const queryParam = ajaxConfig.args[queryParamName]; + + const otherArgs: RequestArgs = {}; + for (const key in ajaxConfig.args) { + if (key !== "query" && key !== "update") { + otherArgs[key] = ajaxConfig.args[key]; + } + } + + // Build the query string using here-string for easy editing + if (queryParam) { + // Handle both string and string[] cases - use first element if array + const queryText = Array.isArray(queryParam) ? queryParam[0] : queryParam; + lines.push(`$${queryParamName} = @"`); + lines.push(queryText); + lines.push(`"@`); + lines.push(""); + } + + // Build the body with the query variable and any other parameters + // The query must be URL-encoded for application/x-www-form-urlencoded + let bodyExpression: string; + const urlEncodeExpr = `[System.Net.WebUtility]::UrlEncode($${queryParamName})`; + if (queryParam && Object.keys(otherArgs).length > 0) { + // Both query variable and other args + const otherArgsString = queryString.stringify(otherArgs); + bodyExpression = `"${queryParamName}=$(${urlEncodeExpr})&${escapePowerShellString(otherArgsString)}"`; + } else if (queryParam) { + // Only query variable - use subexpression for URL encoding + bodyExpression = `"${queryParamName}=$(${urlEncodeExpr})"`; + } else { + // Only other args (shouldn't happen, but handle it) + const otherArgsString = queryString.stringify(otherArgs); + bodyExpression = `"${escapePowerShellString(otherArgsString)}"`; + } + lines.push("$params = @{"); lines.push(` Uri = "${escapePowerShellString(url)}"`); lines.push(` Method = "Post"`); @@ -533,8 +571,8 @@ export function getAsPowerShellString(yasqe: Yasqe, _config?: Config["requestCon lines.push(" }"); } lines.push(` ContentType = "application/x-www-form-urlencoded"`); - lines.push(` Body = "${escapePowerShellString(body)}"`); - lines.push(` OutFile = "result.${fileExtension}"`); + lines.push(` Body = ${bodyExpression}`); + lines.push(` OutFile = "sparql-generated.${fileExtension}"`); lines.push("}"); } else { // Handle other methods (PUT, DELETE, etc.) @@ -552,7 +590,7 @@ export function getAsPowerShellString(yasqe: Yasqe, _config?: Config["requestCon lines.push(` ContentType = "application/x-www-form-urlencoded"`); lines.push(` Body = "${body.replace(/"/g, '`"')}"`); } - lines.push(` OutFile = "result.${fileExtension}"`); + lines.push(` OutFile = "sparql-generated.${fileExtension}"`); lines.push("}"); }