Skip to content

Commit 7fa16b5

Browse files
authored
Merge pull request #74 from rdf-ext/parameters
Added support for custom parameters
2 parents eb727e7 + 00e62d8 commit 7fa16b5

16 files changed

+1871
-2147
lines changed

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,14 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## [3.1.0] - 2025-11-11
9+
10+
### Added
11+
12+
- support for URL parameters in constructor and method calls
13+
- support for standard query parameters (`defaultGraph` and `namedGraph`)
14+
- support for standard update parameters (`usingGraph` and `usingNamedGraph`)
15+
816
## [3.0.0] - 2024-02-18
917

1018
### Added

ParsingQuery.js

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,11 @@ class ParsingQuery extends StreamQuery {
1515
* @param {Object} options
1616
* @param {Headers} [options.headers] additional request headers
1717
* @param {'get'|'postUrlencoded'|'postDirect'} [options.operation='get'] SPARQL Protocol operation
18+
* @param {Object} [options.parameters] additional request parameters
1819
* @return {Promise<DatasetCore>}
1920
*/
20-
async construct (query, { headers, operation } = {}) {
21-
const quads = await chunks(await super.construct(query, { headers, operation }))
21+
async construct (query, { headers, operation, parameters } = {}) {
22+
const quads = await chunks(await super.construct(query, { headers, operation, parameters }))
2223

2324
return this.client.factory.dataset(quads)
2425
}
@@ -30,10 +31,11 @@ class ParsingQuery extends StreamQuery {
3031
* @param {Object} [options]
3132
* @param {Headers} [options.headers] additional request headers
3233
* @param {'get'|'postUrlencoded'|'postDirect'} [options.operation='get'] SPARQL Protocol operation
34+
* @param {Object} [options.parameters] additional request parameters
3335
* @return {Promise<Array<Object.<string, Term>>>}
3436
*/
35-
async select (query, { headers, operation } = {}) {
36-
return chunks(await super.select(query, { headers, operation }))
37+
async select (query, { headers, operation, parameters } = {}) {
38+
return chunks(await super.select(query, { headers, operation, parameters }))
3739
}
3840
}
3941

RawQuery.js

Lines changed: 46 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import mergeHeaders from './lib/mergeHeaders.js'
2+
import mergeParameters from './lib/mergeParameters.js'
23

34
/**
45
* A query implementation that prepares URLs and headers for SPARQL queries and returns the raw fetch response.
@@ -17,56 +18,83 @@ class RawQuery {
1718
*
1819
* @param {string} query ASK query
1920
* @param {Object} [options]
21+
* @param {string[]} [options.defaultGraph] default graph URI parameter
2022
* @param {Headers} [options.headers] additional request headers
23+
* @param {string[]} [options.namedGraph] named graph URI parameter
2124
* @param {'get'|'postUrlencoded'|'postDirect'} [options.operation='get'] SPARQL Protocol operation
25+
* @param {Object} [options.parameters] additional request parameters
2226
* @return {Promise<Response>}
2327
*/
24-
async ask (query, { headers, operation = 'get' } = {}) {
28+
async ask (query, { defaultGraph, headers, namedGraph, operation = 'get', parameters } = {}) {
2529
headers = mergeHeaders(headers)
2630

2731
if (!headers.has('accept')) {
2832
headers.set('accept', 'application/sparql-results+json')
2933
}
3034

31-
return this.client[operation](query, { headers })
35+
parameters = mergeParameters(
36+
parameters,
37+
{ 'default-graph-uri': defaultGraph },
38+
{ 'named-graph-uri': namedGraph }
39+
)
40+
41+
return this.client[operation](query, { headers, parameters })
3242
}
3343

3444
/**
3545
* Sends a request for a CONSTRUCT or DESCRIBE query
3646
*
3747
* @param {string} query CONSTRUCT or DESCRIBE query
3848
* @param {Object} [options]
49+
* @param {string[]} [options.defaultGraph] default graph URI parameter
3950
* @param {Headers} [options.headers] additional request headers
51+
* @param {string[]} [options.namedGraph] named graph URI parameter
4052
* @param {'get'|'postUrlencoded'|'postDirect'} [options.operation='get'] SPARQL Protocol operation
53+
* @param {Object} [options.parameters] additional request parameters
4154
* @return {Promise<Response>}
4255
*/
43-
async construct (query, { headers, operation = 'get' } = {}) {
56+
async construct (query, { defaultGraph, headers, namedGraph, operation = 'get', parameters = {} } = {}) {
4457
headers = mergeHeaders(headers)
4558

4659
if (!headers.has('accept')) {
47-
headers.set('accept', 'application/n-triples')
60+
headers.set('accept', 'application/n-triples, text/turtle')
4861
}
4962

50-
return this.client[operation](query, { headers })
63+
parameters = mergeParameters(
64+
parameters,
65+
{ 'default-graph-uri': defaultGraph },
66+
{ 'named-graph-uri': namedGraph }
67+
)
68+
69+
return this.client[operation](query, { headers, operation, parameters })
5170
}
5271

5372
/**
5473
* Sends a request for a SELECT query
5574
*
5675
* @param {string} query SELECT query
5776
* @param {Object} [options]
77+
* @param {string[]} [options.defaultGraph] default graph URI parameter
5878
* @param {Headers} [options.headers] additional request headers
79+
* @param {string[]} [options.namedGraph] named graph URI parameter
5980
* @param {'get'|'postUrlencoded'|'postDirect'} [options.operation='get'] SPARQL Protocol operation
81+
* @param {Object} [options.parameters] additional request parameters
6082
* @return {Promise<Response>}
6183
*/
62-
async select (query, { headers, operation = 'get' } = {}) {
84+
async select (query, { defaultGraph, headers, namedGraph, operation = 'get', parameters = {} } = {}) {
6385
headers = mergeHeaders(headers)
6486

6587
if (!headers.has('accept')) {
6688
headers.set('accept', 'application/sparql-results+json')
6789
}
6890

69-
return this.client[operation](query, { headers })
91+
parameters = mergeParameters(
92+
parameters,
93+
{ 'default-graph-uri': defaultGraph },
94+
{ 'named-graph-uri': namedGraph }
95+
)
96+
97+
return this.client[operation](query, { headers, parameters })
7098
}
7199

72100
/**
@@ -76,16 +104,25 @@ class RawQuery {
76104
* @param {Object} [options]
77105
* @param {Headers} [options.headers] additional request headers
78106
* @param {'get'|'postUrlencoded'|'postDirect'} [options.operation='postUrlencoded'] SPARQL Protocol operation
107+
* @param {Object} [options.parameters] additional request parameters
108+
* @param {string[]} [options.usingGraph] using graph URI parameter
109+
* @param {string[]} [options.usingNamedGraph] using named graph URI parameter
79110
* @return {Promise<Response>}
80111
*/
81-
async update (query, { headers, operation = 'postUrlencoded' } = {}) {
112+
async update (query, { headers, operation = 'postUrlencoded', parameters, usingGraph, usingNamedGraph } = {}) {
82113
headers = mergeHeaders(headers)
83114

84115
if (!headers.has('accept')) {
85116
headers.set('accept', '*/*')
86117
}
87118

88-
return this.client[operation](query, { headers, update: true })
119+
parameters = mergeParameters(
120+
parameters,
121+
{ 'using-graph-uri': usingGraph },
122+
{ 'using-named-graph-uri': usingNamedGraph }
123+
)
124+
125+
return this.client[operation](query, { headers, parameters, update: true })
89126
}
90127
}
91128

SimpleClient.js

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import defaultFetch from 'nodeify-fetch'
22
import mergeHeaders from './lib/mergeHeaders.js'
3+
import mergeParameters from './lib/mergeParameters.js'
34
import RawQuery from './RawQuery.js'
45

56
/**
@@ -12,6 +13,7 @@ import RawQuery from './RawQuery.js'
1213
* @property {factory} fetch
1314
* @property {Headers} headers
1415
* @property {string} password
16+
* @property {Object} parameters
1517
* @property {string} storeUrl
1618
* @property {string} updateUrl
1719
* @property {string} user
@@ -55,6 +57,7 @@ class SimpleClient {
5557
* @param {fetch} [options.fetch=nodeify-fetch] fetch implementation
5658
* @param {Headers} [options.headers] headers sent with every request
5759
* @param {string} [options.password] password used for basic authentication
60+
* @param {Object} [options.parameters] parameters sent with every request
5861
* @param {string} [options.storeUrl] SPARQL Graph Store URL
5962
* @param {string} [options.updateUrl] SPARQL update endpoint URL
6063
* @param {string} [options.user] user used for basic authentication
@@ -66,6 +69,7 @@ class SimpleClient {
6669
factory,
6770
fetch = defaultFetch,
6871
headers,
72+
parameters,
6973
password,
7074
storeUrl,
7175
updateUrl,
@@ -81,6 +85,7 @@ class SimpleClient {
8185
this.factory = factory
8286
this.fetch = fetch
8387
this.headers = new Headers(headers)
88+
this.parameters = parameters
8489
this.password = password
8590
this.storeUrl = storeUrl
8691
this.updateUrl = updateUrl
@@ -100,10 +105,11 @@ class SimpleClient {
100105
* @param {string} query SPARQL query
101106
* @param {Object} options
102107
* @param {Headers} [options.headers] additional request headers
108+
* @param {Object} [options.parameters] additional request parameters
103109
* @param {boolean} [options.update=false] send the request to the updateUrl
104110
* @return {Promise<Response>}
105111
*/
106-
async get (query, { headers, update = false } = {}) {
112+
async get (query, { headers, parameters, update = false } = {}) {
107113
let url = null
108114

109115
if (!update) {
@@ -114,6 +120,12 @@ class SimpleClient {
114120
url.searchParams.append('update', query)
115121
}
116122

123+
parameters = mergeParameters(this.parameters, parameters)
124+
125+
for (const [key, value] of parameters.entries()) {
126+
url.searchParams.append(key, value)
127+
}
128+
117129
return this.fetch(url.toString().replace(/\+/g, '%20'), {
118130
method: 'GET',
119131
headers: mergeHeaders(this.headers, headers)
@@ -128,10 +140,11 @@ class SimpleClient {
128140
* @param {string} query SPARQL query
129141
* @param {Object} options
130142
* @param {Headers} [options.headers] additional request headers
143+
* @param {Object} [options.parameters] additional request parameters
131144
* @param {boolean} [options.update=false] send the request to the updateUrl
132145
* @return {Promise<Response>}
133146
*/
134-
async postDirect (query, { headers, update = false } = {}) {
147+
async postDirect (query, { headers, parameters, update = false } = {}) {
135148
let url = null
136149

137150
if (!update) {
@@ -146,6 +159,12 @@ class SimpleClient {
146159
headers.set('content-type', 'application/sparql-query; charset=utf-8')
147160
}
148161

162+
parameters = mergeParameters(this.parameters, parameters)
163+
164+
for (const [key, value] of parameters.entries()) {
165+
url.searchParams.append(key, value)
166+
}
167+
149168
return this.fetch(url, {
150169
method: 'POST',
151170
headers,
@@ -160,19 +179,20 @@ class SimpleClient {
160179
* @param {string} query SPARQL query
161180
* @param {Object} options
162181
* @param {Headers} [options.headers] additional request headers
182+
* @param {Object} [options.parameters] additional request parameters
163183
* @param {boolean} [options.update=false] send the request to the updateUrl
164184
* @return {Promise<Response>}
165185
*/
166-
async postUrlencoded (query, { headers, update = false } = {}) {
186+
async postUrlencoded (query, { headers, parameters, update = false } = {}) {
167187
let url = null
168-
let body = null
188+
const body = new URLSearchParams()
169189

170190
if (!update) {
171191
url = new URL(this.endpointUrl)
172-
body = `query=${encodeURIComponent(query)}`
192+
body.append('query', query)
173193
} else {
174194
url = new URL(this.updateUrl)
175-
body = `update=${encodeURIComponent(query)}`
195+
body.append('update', query)
176196
}
177197

178198
headers = mergeHeaders(this.headers, headers)
@@ -181,10 +201,16 @@ class SimpleClient {
181201
headers.set('content-type', 'application/x-www-form-urlencoded')
182202
}
183203

204+
parameters = mergeParameters(this.parameters, parameters)
205+
206+
for (const [key, value] of parameters.entries()) {
207+
body.append(key, value)
208+
}
209+
184210
return this.fetch(url, {
185211
method: 'POST',
186212
headers,
187-
body
213+
body: body.toString()
188214
})
189215
}
190216
}

StreamQuery.js

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import N3Parser from '@rdfjs/parser-n3'
22
import asyncToReadabe from './lib/asyncToReadabe.js'
33
import checkResponse from './lib/checkResponse.js'
4-
import mergeHeaders from './lib/mergeHeaders.js'
54
import RawQuery from './RawQuery.js'
65
import ResultParser from './ResultParser.js'
76

@@ -19,10 +18,11 @@ class StreamQuery extends RawQuery {
1918
* @param {Object} [options]
2019
* @param {Headers} [options.headers] additional request headers
2120
* @param {'get'|'postUrlencoded'|'postDirect'} [options.operation='get'] SPARQL Protocol operation
21+
* @param {Object} [options.parameters] additional request parameters
2222
* @return {Promise<boolean>}
2323
*/
24-
async ask (query, { headers, operation } = {}) {
25-
const res = await super.ask(query, { headers, operation })
24+
async ask (query, { headers, operation, parameters } = {}) {
25+
const res = await super.ask(query, { headers, operation, parameters })
2626

2727
await checkResponse(res)
2828

@@ -38,17 +38,12 @@ class StreamQuery extends RawQuery {
3838
* @param {Object} [options]
3939
* @param {Headers} [options.headers] additional request headers
4040
* @param {'get'|'postUrlencoded'|'postDirect'} [options.operation='get'] SPARQL Protocol operation
41+
* @param {Object} [options.parameters] additional request parameters
4142
* @return {Readable}
4243
*/
43-
construct (query, { headers, operation } = {}) {
44+
construct (query, { headers, operation, parameters } = {}) {
4445
return asyncToReadabe(async () => {
45-
headers = mergeHeaders(headers)
46-
47-
if (!headers.has('accept')) {
48-
headers.set('accept', 'application/n-triples, text/turtle')
49-
}
50-
51-
const res = await super.construct(query, { headers, operation })
46+
const res = await super.construct(query, { headers, operation, parameters })
5247

5348
await checkResponse(res)
5449

@@ -65,11 +60,12 @@ class StreamQuery extends RawQuery {
6560
* @param {Object} [options]
6661
* @param {Headers} [options.headers] additional request headers
6762
* @param {'get'|'postUrlencoded'|'postDirect'} [options.operation='get'] SPARQL Protocol operation
63+
* @param {Object} [options.parameters] additional request parameters
6864
* @return {Readable}
6965
*/
70-
select (query, { headers, operation } = {}) {
66+
select (query, { headers, operation, parameters } = {}) {
7167
return asyncToReadabe(async () => {
72-
const res = await super.select(query, { headers, operation })
68+
const res = await super.select(query, { headers, operation, parameters })
7369

7470
await checkResponse(res)
7571

@@ -86,10 +82,11 @@ class StreamQuery extends RawQuery {
8682
* @param {Object} [options]
8783
* @param {Headers} [options.headers] additional request headers
8884
* @param {'get'|'postUrlencoded'|'postDirect'} [options.operation='postUrlencoded'] SPARQL Protocol operation
85+
* @param {Object} [options.parameters] additional request parameters
8986
* @return {Promise<void>}
9087
*/
91-
async update (query, { headers, operation } = {}) {
92-
const res = await super.update(query, { headers, operation })
88+
async update (query, { headers, operation, parameters } = {}) {
89+
const res = await super.update(query, { headers, operation, parameters })
9390

9491
await checkResponse(res)
9592
}

0 commit comments

Comments
 (0)