Skip to content

Commit 2f476d9

Browse files
committed
fix: merge fetch Response metadata (headers, status) with the awaited body content of the response (query results, usually JSON or RDF). Currently only the response body content is passed to the YASR Parser, preventing it to properly figure out the type of a responses. This fix enables to properly display a CONSTRUCT or DESCRIBE query results in the YASR table.
1 parent 6955cec commit 2f476d9

File tree

2 files changed

+47
-22
lines changed

2 files changed

+47
-22
lines changed

packages/yasqe/src/sparql.ts

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,12 @@ function getRequestConfigSettings(yasqe: Yasqe, conf?: Partial<Config["requestCo
1919
// type callback = AjaxConfig.callbacks['complete'];
2020
export function getAjaxConfig(
2121
yasqe: Yasqe,
22-
_config: Partial<Config["requestConfig"]> = {}
22+
_config: Partial<Config["requestConfig"]> = {},
2323
): PopulatedAjaxConfig | undefined {
2424
const config: RequestConfig<Yasqe> = merge(
2525
{},
2626
getRequestConfigSettings(yasqe, yasqe.config.requestConfig),
27-
getRequestConfigSettings(yasqe, _config)
27+
getRequestConfigSettings(yasqe, _config),
2828
);
2929
if (!config.endpoint || config.endpoint.length == 0) return; // nothing to query!
3030

@@ -94,18 +94,21 @@ export async function executeQuery(yasqe: Yasqe, config?: YasqeAjaxConfig): Prom
9494
const request = new Request(populatedConfig.url, fetchOptions);
9595
yasqe.emit("query", request, abortController);
9696
const response = await fetch(request);
97-
let result = await response.text();
98-
try {
99-
result = JSON.parse(result);
100-
} catch (e) {
101-
// ignore
102-
}
10397
if (!response.ok) {
104-
throw new Error(result || response.statusText);
98+
throw new Error((await response.text()) || response.statusText);
10599
}
106-
yasqe.emit("queryResponse", result, Date.now() - queryStart);
107-
yasqe.emit("queryResults", result, Date.now() - queryStart);
108-
return result;
100+
// Await the response content and merge with the `Response` object
101+
const queryResponse = {
102+
ok: response.ok,
103+
status: response.status,
104+
statusText: response.statusText,
105+
headers: response.headers,
106+
type: response.type,
107+
content: await response.text(),
108+
};
109+
yasqe.emit("queryResponse", queryResponse, Date.now() - queryStart);
110+
yasqe.emit("queryResults", queryResponse.content, Date.now() - queryStart);
111+
return queryResponse;
109112
} catch (e) {
110113
if (e instanceof Error && e.message === "Aborted") {
111114
// The query was aborted. We should not do or draw anything
@@ -153,7 +156,7 @@ export function getUrlArguments(yasqe: Yasqe, _config: Config["requestConfig"]):
153156
args.reduce((argsObject: { [key: string]: string[] }, arg) => {
154157
argsObject[arg.name] ? argsObject[arg.name].push(arg.value) : (argsObject[arg.name] = [arg.value]);
155158
return argsObject;
156-
}, {})
159+
}, {}),
157160
);
158161

159162
return data;

packages/yasr/src/parsers/index.ts

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -55,25 +55,50 @@ const applyMustacheToLiterals: Parser.PostProcessBinding = (binding: Parser.Bind
5555
}
5656
return binding;
5757
};
58+
59+
/**
60+
* Response object from a fetch request with an additional `.content` property containing the awaited response content
61+
*/
62+
type QueryResponse = Response & {
63+
content: string;
64+
};
65+
66+
/**
67+
* Parser class for handling query responses from various formats.
68+
*
69+
* This class processes responses from SPARQL endpoints and converts them into standardized formats for further processing.
70+
* It can handle JSON, XML, CSV, TSV, and Turtle responses, detecting the format either from content-type headers
71+
* or by attempting to parse the content.
72+
*
73+
* The parser can process:
74+
* - Direct `QueryResponse` objects (regular fetch response with additional content property with the awaited response content)
75+
* - ResponseSummary objects
76+
* - Error objects
77+
* - Raw response data
78+
*
79+
* It provides methods to access parsed data in standardized formats, error information,
80+
* and utilities to convert the data for storage or export.
81+
*/
5882
class Parser {
59-
private res: Response | undefined;
83+
private res: QueryResponse | undefined;
6084
private summary: Parser.ResponseSummary | undefined;
6185
private errorSummary: Parser.ErrorSummary | undefined;
6286
private error: Error | undefined;
6387
private type: "json" | "xml" | "csv" | "tsv" | "ttl" | undefined;
6488
private executionTime: number | undefined;
65-
constructor(responseOrObject: Parser.ResponseSummary | Response | Error | any, executionTime?: number) {
89+
90+
constructor(responseOrObject: Parser.ResponseSummary | QueryResponse | Error | any, executionTime?: number) {
6691
if (responseOrObject.executionTime) this.executionTime = responseOrObject.executionTime;
6792
if (executionTime) this.executionTime = executionTime; // Parameter has priority
6893
if (responseOrObject instanceof Error) {
6994
this.error = responseOrObject;
70-
} else if ((<any>responseOrObject).xhr) {
71-
this.setResponse(<Response>responseOrObject);
95+
} else if ((<any>responseOrObject).content) {
96+
this.setResponse(<QueryResponse>responseOrObject);
7297
} else {
7398
this.setSummary(<Parser.ResponseSummary>responseOrObject);
7499
}
75100
}
76-
public setResponse(res: Response) {
101+
public setResponse(res: QueryResponse) {
77102
this.res = res;
78103
}
79104
public setSummary(summary: Parser.ResponseSummary | any) {
@@ -130,6 +155,7 @@ class Parser {
130155
}
131156
private getData(): any {
132157
if (this.res) {
158+
if (this.res.content) return this.res.content;
133159
if (this.res.body) return this.res.body;
134160
if (this.res.text) return this.res.text; //probably a construct or something
135161
}
@@ -236,10 +262,6 @@ class Parser {
236262
return data;
237263
}
238264

239-
getOriginalResponse() {
240-
return this.res?.body;
241-
}
242-
243265
getType() {
244266
if (!this.type) this.getAsJson(); //detects type as well
245267
return this.type;

0 commit comments

Comments
 (0)