ldkit 2.1.1 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/esm/library/engine/query_engine.js +5 -5
- package/esm/library/engine/query_engine_proxy.js +2 -4
- package/esm/library/engine/query_resolvers.js +29 -6
- package/esm/library/rdf.js +20 -10
- package/esm/library/utils.js +1 -0
- package/package.json +4 -2
- package/script/library/engine/query_engine.js +5 -5
- package/script/library/engine/query_engine_proxy.js +1 -3
- package/script/library/engine/query_resolvers.js +29 -6
- package/script/library/rdf.js +20 -10
- package/script/library/utils.js +5 -0
- package/types/library/engine/query_engine.d.ts +1 -5
- package/types/library/options.d.ts +1 -0
- package/types/library/rdf.d.ts +1 -1
- package/types/library/utils.d.ts +1 -0
|
@@ -41,21 +41,21 @@ export class QueryEngine {
|
|
|
41
41
|
getFetch(context) {
|
|
42
42
|
return context && context.fetch ? context.fetch : fetch;
|
|
43
43
|
}
|
|
44
|
-
query(body, responseType, context) {
|
|
44
|
+
query(body, requestType, responseType, context) {
|
|
45
45
|
const endpoint = this.getSparqlEndpoint(context);
|
|
46
46
|
const fetchFn = this.getFetch(context);
|
|
47
47
|
return fetchFn(endpoint, {
|
|
48
48
|
method: "POST",
|
|
49
49
|
headers: {
|
|
50
50
|
"accept": responseType,
|
|
51
|
-
"content-type":
|
|
51
|
+
"content-type": `${requestType}; charset=UTF-8`,
|
|
52
52
|
},
|
|
53
|
-
body
|
|
53
|
+
body,
|
|
54
54
|
});
|
|
55
55
|
}
|
|
56
56
|
async queryAndResolve(type, query, context) {
|
|
57
57
|
const responseType = getResponseTypes(type).join(", ");
|
|
58
|
-
const response = await this.query(
|
|
58
|
+
const response = await this.query(query, "application/sparql-query", responseType, context);
|
|
59
59
|
if (!response.ok) {
|
|
60
60
|
await response.body?.cancel();
|
|
61
61
|
throw new Error(`Invalid query response status '${response.status} ${response.statusText}'`);
|
|
@@ -100,6 +100,6 @@ export class QueryEngine {
|
|
|
100
100
|
* @returns Nothing
|
|
101
101
|
*/
|
|
102
102
|
async queryVoid(query, context) {
|
|
103
|
-
await this.query(
|
|
103
|
+
await this.query(query, "application/sparql-update", "application/sparql-results+json", context);
|
|
104
104
|
}
|
|
105
105
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { quadsToGraph } from "../rdf.js";
|
|
2
2
|
export class QueryEngineProxy {
|
|
3
3
|
constructor(engine, context) {
|
|
4
4
|
Object.defineProperty(this, "engine", {
|
|
@@ -25,9 +25,7 @@ export class QueryEngineProxy {
|
|
|
25
25
|
}
|
|
26
26
|
async queryGraph(query) {
|
|
27
27
|
const quadStream = await this.engine.queryQuads(query, this.context);
|
|
28
|
-
|
|
29
|
-
const store = new N3.Store(quads);
|
|
30
|
-
return quadsToGraph(store);
|
|
28
|
+
return quadsToGraph(quadStream);
|
|
31
29
|
}
|
|
32
30
|
queryVoid(query) {
|
|
33
31
|
return this.engine.queryVoid(query, this.context);
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { readableFromWeb } from "../utils.js";
|
|
1
2
|
import { BindingsFactory, N3, QuadFactory } from "../rdf.js";
|
|
2
3
|
import { ArrayIterator, MappingIterator, TreeIterator, } from "../asynciterator.js";
|
|
3
4
|
class QueryResolver {
|
|
@@ -19,7 +20,6 @@ class BindingsJsonResolver extends QueryResolver {
|
|
|
19
20
|
}
|
|
20
21
|
const bindingsFactory = new BindingsFactory();
|
|
21
22
|
const bindingsIterator = new ArrayIterator(json.results.bindings);
|
|
22
|
-
// TODO: review the unknown type cast
|
|
23
23
|
return new MappingIterator(bindingsIterator, (i) => bindingsFactory.fromJson(i));
|
|
24
24
|
}
|
|
25
25
|
}
|
|
@@ -31,15 +31,35 @@ class QuadsJsonResolver extends QueryResolver {
|
|
|
31
31
|
}
|
|
32
32
|
const quadFactory = new QuadFactory();
|
|
33
33
|
const treeIterator = new TreeIterator(json);
|
|
34
|
-
// TODO: review the unknown type cast
|
|
35
34
|
return new MappingIterator(treeIterator, (i) => quadFactory.fromJson(i));
|
|
36
35
|
}
|
|
37
36
|
}
|
|
37
|
+
const createN3Stream = async (response, format) => {
|
|
38
|
+
if (response.body === null) {
|
|
39
|
+
throw new Error("Response body is null, but it should contain quads from the SPARQL query");
|
|
40
|
+
}
|
|
41
|
+
const stream = readableFromWeb(response.body);
|
|
42
|
+
const parser = new N3.StreamParser({ format });
|
|
43
|
+
return await parser.import(stream);
|
|
44
|
+
};
|
|
45
|
+
class QuadsNTriplesResolver extends QueryResolver {
|
|
46
|
+
resolve(response) {
|
|
47
|
+
return createN3Stream(response, "N-Triples");
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
class QuadsNQuadsResolver extends QueryResolver {
|
|
51
|
+
resolve(response) {
|
|
52
|
+
return createN3Stream(response, "N-Quads");
|
|
53
|
+
}
|
|
54
|
+
}
|
|
38
55
|
class QuadsTurtleResolver extends QueryResolver {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
56
|
+
resolve(response) {
|
|
57
|
+
return createN3Stream(response, "Turtle");
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
class QuadsTrigResolver extends QueryResolver {
|
|
61
|
+
resolve(response) {
|
|
62
|
+
return createN3Stream(response, "TriG");
|
|
43
63
|
}
|
|
44
64
|
}
|
|
45
65
|
const resolvers = {
|
|
@@ -51,7 +71,10 @@ const resolvers = {
|
|
|
51
71
|
},
|
|
52
72
|
"quads": {
|
|
53
73
|
"application/rdf+json": new QuadsJsonResolver(),
|
|
74
|
+
"application/n-triples": new QuadsNTriplesResolver(),
|
|
75
|
+
"application/n-quads": new QuadsNQuadsResolver(),
|
|
54
76
|
"text/turtle": new QuadsTurtleResolver(),
|
|
77
|
+
"application/trig": new QuadsTrigResolver(),
|
|
55
78
|
},
|
|
56
79
|
};
|
|
57
80
|
export const getResponseTypes = (resolverType) => Object.keys(resolvers[resolverType]);
|
package/esm/library/rdf.js
CHANGED
|
@@ -1,17 +1,27 @@
|
|
|
1
1
|
export { fromRdf, toRdf } from "rdf-literal";
|
|
2
|
+
import { quadToStringQuad } from "rdf-string";
|
|
2
3
|
import { DataFactory, DefaultGraph } from "rdf-data-factory";
|
|
3
4
|
export { DataFactory, DefaultGraph };
|
|
4
5
|
export * as N3 from "n3";
|
|
5
|
-
export const quadsToGraph = (
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
const
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
6
|
+
export const quadsToGraph = (quadStream) => {
|
|
7
|
+
return new Promise((resolve, reject) => {
|
|
8
|
+
const graph = new Map();
|
|
9
|
+
const included = {};
|
|
10
|
+
quadStream.on("data", (quad) => {
|
|
11
|
+
const hash = Object.values(quadToStringQuad(quad)).join(" ");
|
|
12
|
+
if (included[hash]) {
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
included[hash] = true;
|
|
16
|
+
const s = quad.subject.value;
|
|
17
|
+
const p = quad.predicate.value;
|
|
18
|
+
const predicateMap = graph.get(s) || graph.set(s, new Map()).get(s);
|
|
19
|
+
const termArray = predicateMap.get(p) || predicateMap.set(p, []).get(p);
|
|
20
|
+
termArray.push(quad.object);
|
|
21
|
+
});
|
|
22
|
+
quadStream.on("end", () => resolve(graph));
|
|
23
|
+
quadStream.on("error", reject);
|
|
24
|
+
});
|
|
15
25
|
};
|
|
16
26
|
export class TermFactory {
|
|
17
27
|
constructor(dataFactory = new DataFactory()) {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { readableFromWeb } from "readable-from-web";
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"main": "./script/mod.js",
|
|
4
4
|
"types": "./types/mod.d.ts",
|
|
5
5
|
"name": "ldkit",
|
|
6
|
-
"version": "2.
|
|
6
|
+
"version": "2.2.0",
|
|
7
7
|
"description": "LDkit, a Linked Data query toolkit for TypeScript developers",
|
|
8
8
|
"homepage": "https://ldkit.io",
|
|
9
9
|
"author": "Karel Klima <karelklima@gmail.com> (https://karelklima.com)",
|
|
@@ -70,6 +70,8 @@
|
|
|
70
70
|
"asynciterator": "^3.9.0",
|
|
71
71
|
"n3": "^1.23.1",
|
|
72
72
|
"rdf-data-factory": "^2.0.2",
|
|
73
|
-
"rdf-literal": "^2.0.0"
|
|
73
|
+
"rdf-literal": "^2.0.0",
|
|
74
|
+
"rdf-string": "^2.0.0",
|
|
75
|
+
"readable-from-web": "^0.0.4"
|
|
74
76
|
}
|
|
75
77
|
}
|
|
@@ -44,21 +44,21 @@ class QueryEngine {
|
|
|
44
44
|
getFetch(context) {
|
|
45
45
|
return context && context.fetch ? context.fetch : fetch;
|
|
46
46
|
}
|
|
47
|
-
query(body, responseType, context) {
|
|
47
|
+
query(body, requestType, responseType, context) {
|
|
48
48
|
const endpoint = this.getSparqlEndpoint(context);
|
|
49
49
|
const fetchFn = this.getFetch(context);
|
|
50
50
|
return fetchFn(endpoint, {
|
|
51
51
|
method: "POST",
|
|
52
52
|
headers: {
|
|
53
53
|
"accept": responseType,
|
|
54
|
-
"content-type":
|
|
54
|
+
"content-type": `${requestType}; charset=UTF-8`,
|
|
55
55
|
},
|
|
56
|
-
body
|
|
56
|
+
body,
|
|
57
57
|
});
|
|
58
58
|
}
|
|
59
59
|
async queryAndResolve(type, query, context) {
|
|
60
60
|
const responseType = (0, query_resolvers_js_1.getResponseTypes)(type).join(", ");
|
|
61
|
-
const response = await this.query(
|
|
61
|
+
const response = await this.query(query, "application/sparql-query", responseType, context);
|
|
62
62
|
if (!response.ok) {
|
|
63
63
|
await response.body?.cancel();
|
|
64
64
|
throw new Error(`Invalid query response status '${response.status} ${response.statusText}'`);
|
|
@@ -103,7 +103,7 @@ class QueryEngine {
|
|
|
103
103
|
* @returns Nothing
|
|
104
104
|
*/
|
|
105
105
|
async queryVoid(query, context) {
|
|
106
|
-
await this.query(
|
|
106
|
+
await this.query(query, "application/sparql-update", "application/sparql-results+json", context);
|
|
107
107
|
}
|
|
108
108
|
}
|
|
109
109
|
exports.QueryEngine = QueryEngine;
|
|
@@ -28,9 +28,7 @@ class QueryEngineProxy {
|
|
|
28
28
|
}
|
|
29
29
|
async queryGraph(query) {
|
|
30
30
|
const quadStream = await this.engine.queryQuads(query, this.context);
|
|
31
|
-
|
|
32
|
-
const store = new rdf_js_1.N3.Store(quads);
|
|
33
|
-
return (0, rdf_js_1.quadsToGraph)(store);
|
|
31
|
+
return (0, rdf_js_1.quadsToGraph)(quadStream);
|
|
34
32
|
}
|
|
35
33
|
queryVoid(query) {
|
|
36
34
|
return this.engine.queryVoid(query, this.context);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.resolve = exports.getResponseTypes = void 0;
|
|
4
|
+
const utils_js_1 = require("../utils.js");
|
|
4
5
|
const rdf_js_1 = require("../rdf.js");
|
|
5
6
|
const asynciterator_js_1 = require("../asynciterator.js");
|
|
6
7
|
class QueryResolver {
|
|
@@ -22,7 +23,6 @@ class BindingsJsonResolver extends QueryResolver {
|
|
|
22
23
|
}
|
|
23
24
|
const bindingsFactory = new rdf_js_1.BindingsFactory();
|
|
24
25
|
const bindingsIterator = new asynciterator_js_1.ArrayIterator(json.results.bindings);
|
|
25
|
-
// TODO: review the unknown type cast
|
|
26
26
|
return new asynciterator_js_1.MappingIterator(bindingsIterator, (i) => bindingsFactory.fromJson(i));
|
|
27
27
|
}
|
|
28
28
|
}
|
|
@@ -34,15 +34,35 @@ class QuadsJsonResolver extends QueryResolver {
|
|
|
34
34
|
}
|
|
35
35
|
const quadFactory = new rdf_js_1.QuadFactory();
|
|
36
36
|
const treeIterator = new asynciterator_js_1.TreeIterator(json);
|
|
37
|
-
// TODO: review the unknown type cast
|
|
38
37
|
return new asynciterator_js_1.MappingIterator(treeIterator, (i) => quadFactory.fromJson(i));
|
|
39
38
|
}
|
|
40
39
|
}
|
|
40
|
+
const createN3Stream = async (response, format) => {
|
|
41
|
+
if (response.body === null) {
|
|
42
|
+
throw new Error("Response body is null, but it should contain quads from the SPARQL query");
|
|
43
|
+
}
|
|
44
|
+
const stream = (0, utils_js_1.readableFromWeb)(response.body);
|
|
45
|
+
const parser = new rdf_js_1.N3.StreamParser({ format });
|
|
46
|
+
return await parser.import(stream);
|
|
47
|
+
};
|
|
48
|
+
class QuadsNTriplesResolver extends QueryResolver {
|
|
49
|
+
resolve(response) {
|
|
50
|
+
return createN3Stream(response, "N-Triples");
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
class QuadsNQuadsResolver extends QueryResolver {
|
|
54
|
+
resolve(response) {
|
|
55
|
+
return createN3Stream(response, "N-Quads");
|
|
56
|
+
}
|
|
57
|
+
}
|
|
41
58
|
class QuadsTurtleResolver extends QueryResolver {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
59
|
+
resolve(response) {
|
|
60
|
+
return createN3Stream(response, "Turtle");
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
class QuadsTrigResolver extends QueryResolver {
|
|
64
|
+
resolve(response) {
|
|
65
|
+
return createN3Stream(response, "TriG");
|
|
46
66
|
}
|
|
47
67
|
}
|
|
48
68
|
const resolvers = {
|
|
@@ -54,7 +74,10 @@ const resolvers = {
|
|
|
54
74
|
},
|
|
55
75
|
"quads": {
|
|
56
76
|
"application/rdf+json": new QuadsJsonResolver(),
|
|
77
|
+
"application/n-triples": new QuadsNTriplesResolver(),
|
|
78
|
+
"application/n-quads": new QuadsNQuadsResolver(),
|
|
57
79
|
"text/turtle": new QuadsTurtleResolver(),
|
|
80
|
+
"application/trig": new QuadsTrigResolver(),
|
|
58
81
|
},
|
|
59
82
|
};
|
|
60
83
|
const getResponseTypes = (resolverType) => Object.keys(resolvers[resolverType]);
|
package/script/library/rdf.js
CHANGED
|
@@ -27,20 +27,30 @@ exports.QuadFactory = exports.BindingsFactory = exports.ReadOnlyBindings = expor
|
|
|
27
27
|
var rdf_literal_1 = require("rdf-literal");
|
|
28
28
|
Object.defineProperty(exports, "fromRdf", { enumerable: true, get: function () { return rdf_literal_1.fromRdf; } });
|
|
29
29
|
Object.defineProperty(exports, "toRdf", { enumerable: true, get: function () { return rdf_literal_1.toRdf; } });
|
|
30
|
+
const rdf_string_1 = require("rdf-string");
|
|
30
31
|
const rdf_data_factory_1 = require("rdf-data-factory");
|
|
31
32
|
Object.defineProperty(exports, "DataFactory", { enumerable: true, get: function () { return rdf_data_factory_1.DataFactory; } });
|
|
32
33
|
Object.defineProperty(exports, "DefaultGraph", { enumerable: true, get: function () { return rdf_data_factory_1.DefaultGraph; } });
|
|
33
34
|
exports.N3 = __importStar(require("n3"));
|
|
34
|
-
const quadsToGraph = (
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
const
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
35
|
+
const quadsToGraph = (quadStream) => {
|
|
36
|
+
return new Promise((resolve, reject) => {
|
|
37
|
+
const graph = new Map();
|
|
38
|
+
const included = {};
|
|
39
|
+
quadStream.on("data", (quad) => {
|
|
40
|
+
const hash = Object.values((0, rdf_string_1.quadToStringQuad)(quad)).join(" ");
|
|
41
|
+
if (included[hash]) {
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
included[hash] = true;
|
|
45
|
+
const s = quad.subject.value;
|
|
46
|
+
const p = quad.predicate.value;
|
|
47
|
+
const predicateMap = graph.get(s) || graph.set(s, new Map()).get(s);
|
|
48
|
+
const termArray = predicateMap.get(p) || predicateMap.set(p, []).get(p);
|
|
49
|
+
termArray.push(quad.object);
|
|
50
|
+
});
|
|
51
|
+
quadStream.on("end", () => resolve(graph));
|
|
52
|
+
quadStream.on("error", reject);
|
|
53
|
+
});
|
|
44
54
|
};
|
|
45
55
|
exports.quadsToGraph = quadsToGraph;
|
|
46
56
|
class TermFactory {
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.readableFromWeb = void 0;
|
|
4
|
+
var readable_from_web_1 = require("readable-from-web");
|
|
5
|
+
Object.defineProperty(exports, "readableFromWeb", { enumerable: true, get: function () { return readable_from_web_1.readableFromWeb; } });
|
|
@@ -16,11 +16,7 @@ import { type ResolverType } from "./query_resolvers.js";
|
|
|
16
16
|
export declare class QueryEngine implements IQueryEngine {
|
|
17
17
|
protected getSparqlEndpoint(context?: QueryContext): string;
|
|
18
18
|
protected getFetch(context?: QueryContext): typeof fetch;
|
|
19
|
-
protected query(body:
|
|
20
|
-
query: string;
|
|
21
|
-
} | {
|
|
22
|
-
update: string;
|
|
23
|
-
}, responseType: string, context?: QueryContext): Promise<Response>;
|
|
19
|
+
protected query(body: string, requestType: "application/sparql-query" | "application/sparql-update", responseType: string, context?: QueryContext): Promise<Response>;
|
|
24
20
|
protected queryAndResolve<T extends ResolverType>(type: T, query: string, context?: QueryContext): Promise<{
|
|
25
21
|
boolean: boolean;
|
|
26
22
|
bindings: RDF.ResultStream<RDF.Bindings>;
|
|
@@ -66,5 +66,6 @@ export declare function resolveOptions(options?: Options): {
|
|
|
66
66
|
extensionFunctions?: Record<string, (args: import("@rdfjs/types").Term[]) => Promise<import("@rdfjs/types").Term>> | undefined;
|
|
67
67
|
explain?: import("@comunica/types").QueryExplainMode | undefined;
|
|
68
68
|
recoverBrokenLinks?: boolean | undefined;
|
|
69
|
+
distinctConstruct?: boolean | undefined;
|
|
69
70
|
};
|
|
70
71
|
export declare function resolveQueryContext(options: Options): QueryContext;
|
package/types/library/rdf.d.ts
CHANGED
|
@@ -7,7 +7,7 @@ export * as N3 from "n3";
|
|
|
7
7
|
export type IRI = string;
|
|
8
8
|
export type Node = Map<IRI, RDF.Term[]>;
|
|
9
9
|
export type Graph = Map<IRI, Node>;
|
|
10
|
-
export declare const quadsToGraph: (
|
|
10
|
+
export declare const quadsToGraph: (quadStream: RDF.ResultStream<RDF.Quad>) => Promise<Graph>;
|
|
11
11
|
export declare namespace RDFJSON {
|
|
12
12
|
type Term = {
|
|
13
13
|
type: "uri" | "literal" | "bnode";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { readableFromWeb } from "readable-from-web";
|