ldkit 2.1.1 → 2.3.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/decoder.js +2 -2
- package/esm/library/encoder.js +3 -4
- 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/translator.js +62 -0
- package/esm/library/utils.js +1 -0
- package/esm/mod.js +1 -0
- package/package.json +4 -2
- package/script/library/decoder.js +6 -6
- package/script/library/encoder.js +2 -3
- 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/translator.js +68 -0
- package/script/library/utils.js +5 -0
- package/script/mod.js +3 -1
- package/types/library/encoder.d.ts +1 -1
- 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/schema/data_types.d.ts +12 -2
- package/types/library/schema/mod.d.ts +1 -1
- package/types/library/translator.d.ts +38 -0
- package/types/library/utils.d.ts +1 -0
- package/types/mod.d.ts +2 -1
package/esm/library/decoder.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { fromRdf } from "./rdf.js";
|
|
2
1
|
import { ldkit } from "../namespaces/ldkit.js";
|
|
3
2
|
import { rdf } from "../namespaces/rdf.js";
|
|
3
|
+
import { translateFromRdf } from "./translator.js";
|
|
4
4
|
export const decode = (graph, schema, options) => {
|
|
5
5
|
return Decoder.decode(graph, schema, options);
|
|
6
6
|
};
|
|
@@ -185,7 +185,7 @@ class Decoder {
|
|
|
185
185
|
return term.value;
|
|
186
186
|
}
|
|
187
187
|
else if (term.termType === "Literal") {
|
|
188
|
-
return
|
|
188
|
+
return translateFromRdf(term);
|
|
189
189
|
}
|
|
190
190
|
else {
|
|
191
191
|
throw new Error(`Unsupported term type to resolve: ${term.termType}`);
|
package/esm/library/encoder.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { DataFactory
|
|
1
|
+
import { DataFactory } from "./rdf.js";
|
|
2
2
|
import { xsd } from "../namespaces/xsd.js";
|
|
3
3
|
import { rdf } from "../namespaces/rdf.js";
|
|
4
4
|
import { ldkit } from "../namespaces/ldkit.js";
|
|
5
|
+
import { translateToRdf } from "./translator.js";
|
|
5
6
|
export const encode = (node, schema, options, includeType = true, variableInitCounter = 0) => {
|
|
6
7
|
return Encoder.encode(node, schema, options, includeType, variableInitCounter);
|
|
7
8
|
};
|
|
@@ -9,9 +10,7 @@ export const encodeValue = (value, datatype, df) => {
|
|
|
9
10
|
if (datatype === ldkit.IRI) {
|
|
10
11
|
return df.namedNode(value);
|
|
11
12
|
}
|
|
12
|
-
return
|
|
13
|
-
datatype: df.namedNode(datatype),
|
|
14
|
-
});
|
|
13
|
+
return translateToRdf(value, datatype);
|
|
15
14
|
};
|
|
16
15
|
class Encoder {
|
|
17
16
|
constructor(options, includeType, variableInitCounter) {
|
|
@@ -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,62 @@
|
|
|
1
|
+
import { DataFactory, fromRdf, toRdf } from "./rdf.js";
|
|
2
|
+
const df = new DataFactory();
|
|
3
|
+
const rdfToNativeHandlers = new Map();
|
|
4
|
+
const nativeToRdfHandlers = new Map();
|
|
5
|
+
/**
|
|
6
|
+
* Registers a data type handler for translating between RDF literals and JavaScript values.
|
|
7
|
+
*
|
|
8
|
+
* In order to register a custom data type handler, the custom data type TypeScript mapping needs
|
|
9
|
+
* to be added to the {@link CustomDataTypes} interface using module augmentation.
|
|
10
|
+
*
|
|
11
|
+
* Two handlers are required:
|
|
12
|
+
* 1) A function to translate from RDF literal value (string) to JavaScript value.
|
|
13
|
+
* 2) A function to translate from JavaScript value to RDF literal value (string).
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```typescript
|
|
17
|
+
* import { registerDataHandler } from "ldkit";
|
|
18
|
+
*
|
|
19
|
+
* const customNumberDataType = "http://example.org/number";
|
|
20
|
+
*
|
|
21
|
+
* declare module "ldkit" {
|
|
22
|
+
* interface CustomDataTypes {
|
|
23
|
+
* [customNumberDataType]: number;
|
|
24
|
+
* }
|
|
25
|
+
* }
|
|
26
|
+
*
|
|
27
|
+
* registerDataHandler(
|
|
28
|
+
* customNumberDataType,
|
|
29
|
+
* (literalValue: string) => parseInt(literalValue),
|
|
30
|
+
* (nativeValue: number) => nativeValue.toString(),
|
|
31
|
+
* );
|
|
32
|
+
* ```
|
|
33
|
+
*
|
|
34
|
+
* @param dataType - The data type to register.
|
|
35
|
+
* @param translateFromRDF - Function to translate from RDF literal to JavaScript value.
|
|
36
|
+
* @param translateToRDF - Function to translate from JavaScript value to RDF literal.
|
|
37
|
+
*/
|
|
38
|
+
export function registerDataHandler(dataType, translateFromRDF, translateToRDF) {
|
|
39
|
+
rdfToNativeHandlers.set(dataType, translateFromRDF);
|
|
40
|
+
nativeToRdfHandlers.set(dataType, translateToRDF);
|
|
41
|
+
}
|
|
42
|
+
export function translateFromRdf(literal) {
|
|
43
|
+
const dataType = literal.datatype.value;
|
|
44
|
+
const customHandler = rdfToNativeHandlers.get(dataType);
|
|
45
|
+
if (customHandler) {
|
|
46
|
+
return customHandler(literal.value);
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
return fromRdf(literal);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
export function translateToRdf(value, dataType) {
|
|
53
|
+
const customHandler = nativeToRdfHandlers.get(dataType);
|
|
54
|
+
if (customHandler) {
|
|
55
|
+
return df.literal(customHandler(value), df.namedNode(dataType));
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
return toRdf(value, {
|
|
59
|
+
datatype: df.namedNode(dataType),
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { readableFromWeb } from "readable-from-web";
|
package/esm/mod.js
CHANGED
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.3.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
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.decode = void 0;
|
|
4
|
-
const rdf_js_1 = require("./rdf.js");
|
|
5
4
|
const ldkit_js_1 = require("../namespaces/ldkit.js");
|
|
6
|
-
const
|
|
5
|
+
const rdf_js_1 = require("../namespaces/rdf.js");
|
|
6
|
+
const translator_js_1 = require("./translator.js");
|
|
7
7
|
const decode = (graph, schema, options) => {
|
|
8
8
|
return Decoder.decode(graph, schema, options);
|
|
9
9
|
};
|
|
@@ -56,8 +56,8 @@ class Decoder {
|
|
|
56
56
|
decode() {
|
|
57
57
|
const output = [];
|
|
58
58
|
for (const [iri, properties] of this.graph) {
|
|
59
|
-
if (properties.has(
|
|
60
|
-
const types = properties.get(
|
|
59
|
+
if (properties.has(rdf_js_1.rdf.type)) {
|
|
60
|
+
const types = properties.get(rdf_js_1.rdf.type);
|
|
61
61
|
for (const type of types) {
|
|
62
62
|
if (type.termType === "NamedNode" && type.value === ldkit_js_1.ldkit.Resource) {
|
|
63
63
|
output.push(this.decodeNode(iri, this.schema));
|
|
@@ -96,7 +96,7 @@ class Decoder {
|
|
|
96
96
|
}
|
|
97
97
|
decodeNodeProperty(nodeIri, node, propertyKey, property) {
|
|
98
98
|
const allTerms = node.get(property["@id"]);
|
|
99
|
-
const terms = property["@id"] !==
|
|
99
|
+
const terms = property["@id"] !== rdf_js_1.rdf.type
|
|
100
100
|
? allTerms
|
|
101
101
|
: allTerms?.filter((term) => term.value !== ldkit_js_1.ldkit.Resource);
|
|
102
102
|
if (!terms) {
|
|
@@ -189,7 +189,7 @@ class Decoder {
|
|
|
189
189
|
return term.value;
|
|
190
190
|
}
|
|
191
191
|
else if (term.termType === "Literal") {
|
|
192
|
-
return (0,
|
|
192
|
+
return (0, translator_js_1.translateFromRdf)(term);
|
|
193
193
|
}
|
|
194
194
|
else {
|
|
195
195
|
throw new Error(`Unsupported term type to resolve: ${term.termType}`);
|
|
@@ -5,6 +5,7 @@ const rdf_js_1 = require("./rdf.js");
|
|
|
5
5
|
const xsd_js_1 = require("../namespaces/xsd.js");
|
|
6
6
|
const rdf_js_2 = require("../namespaces/rdf.js");
|
|
7
7
|
const ldkit_js_1 = require("../namespaces/ldkit.js");
|
|
8
|
+
const translator_js_1 = require("./translator.js");
|
|
8
9
|
const encode = (node, schema, options, includeType = true, variableInitCounter = 0) => {
|
|
9
10
|
return Encoder.encode(node, schema, options, includeType, variableInitCounter);
|
|
10
11
|
};
|
|
@@ -13,9 +14,7 @@ const encodeValue = (value, datatype, df) => {
|
|
|
13
14
|
if (datatype === ldkit_js_1.ldkit.IRI) {
|
|
14
15
|
return df.namedNode(value);
|
|
15
16
|
}
|
|
16
|
-
return (0,
|
|
17
|
-
datatype: df.namedNode(datatype),
|
|
18
|
-
});
|
|
17
|
+
return (0, translator_js_1.translateToRdf)(value, datatype);
|
|
19
18
|
};
|
|
20
19
|
exports.encodeValue = encodeValue;
|
|
21
20
|
class Encoder {
|
|
@@ -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,68 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.translateToRdf = exports.translateFromRdf = exports.registerDataHandler = void 0;
|
|
4
|
+
const rdf_js_1 = require("./rdf.js");
|
|
5
|
+
const df = new rdf_js_1.DataFactory();
|
|
6
|
+
const rdfToNativeHandlers = new Map();
|
|
7
|
+
const nativeToRdfHandlers = new Map();
|
|
8
|
+
/**
|
|
9
|
+
* Registers a data type handler for translating between RDF literals and JavaScript values.
|
|
10
|
+
*
|
|
11
|
+
* In order to register a custom data type handler, the custom data type TypeScript mapping needs
|
|
12
|
+
* to be added to the {@link CustomDataTypes} interface using module augmentation.
|
|
13
|
+
*
|
|
14
|
+
* Two handlers are required:
|
|
15
|
+
* 1) A function to translate from RDF literal value (string) to JavaScript value.
|
|
16
|
+
* 2) A function to translate from JavaScript value to RDF literal value (string).
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```typescript
|
|
20
|
+
* import { registerDataHandler } from "ldkit";
|
|
21
|
+
*
|
|
22
|
+
* const customNumberDataType = "http://example.org/number";
|
|
23
|
+
*
|
|
24
|
+
* declare module "ldkit" {
|
|
25
|
+
* interface CustomDataTypes {
|
|
26
|
+
* [customNumberDataType]: number;
|
|
27
|
+
* }
|
|
28
|
+
* }
|
|
29
|
+
*
|
|
30
|
+
* registerDataHandler(
|
|
31
|
+
* customNumberDataType,
|
|
32
|
+
* (literalValue: string) => parseInt(literalValue),
|
|
33
|
+
* (nativeValue: number) => nativeValue.toString(),
|
|
34
|
+
* );
|
|
35
|
+
* ```
|
|
36
|
+
*
|
|
37
|
+
* @param dataType - The data type to register.
|
|
38
|
+
* @param translateFromRDF - Function to translate from RDF literal to JavaScript value.
|
|
39
|
+
* @param translateToRDF - Function to translate from JavaScript value to RDF literal.
|
|
40
|
+
*/
|
|
41
|
+
function registerDataHandler(dataType, translateFromRDF, translateToRDF) {
|
|
42
|
+
rdfToNativeHandlers.set(dataType, translateFromRDF);
|
|
43
|
+
nativeToRdfHandlers.set(dataType, translateToRDF);
|
|
44
|
+
}
|
|
45
|
+
exports.registerDataHandler = registerDataHandler;
|
|
46
|
+
function translateFromRdf(literal) {
|
|
47
|
+
const dataType = literal.datatype.value;
|
|
48
|
+
const customHandler = rdfToNativeHandlers.get(dataType);
|
|
49
|
+
if (customHandler) {
|
|
50
|
+
return customHandler(literal.value);
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
return (0, rdf_js_1.fromRdf)(literal);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
exports.translateFromRdf = translateFromRdf;
|
|
57
|
+
function translateToRdf(value, dataType) {
|
|
58
|
+
const customHandler = nativeToRdfHandlers.get(dataType);
|
|
59
|
+
if (customHandler) {
|
|
60
|
+
return df.literal(customHandler(value), df.namedNode(dataType));
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
return (0, rdf_js_1.toRdf)(value, {
|
|
64
|
+
datatype: df.namedNode(dataType),
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
exports.translateToRdf = translateToRdf;
|
|
@@ -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; } });
|
package/script/mod.js
CHANGED
|
@@ -14,9 +14,11 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
exports.setGlobalOptions = void 0;
|
|
17
|
+
exports.registerDataHandler = exports.setGlobalOptions = void 0;
|
|
18
18
|
var options_js_1 = require("./library/options.js");
|
|
19
19
|
Object.defineProperty(exports, "setGlobalOptions", { enumerable: true, get: function () { return options_js_1.setGlobalOptions; } });
|
|
20
|
+
var translator_js_1 = require("./library/translator.js");
|
|
21
|
+
Object.defineProperty(exports, "registerDataHandler", { enumerable: true, get: function () { return translator_js_1.registerDataHandler; } });
|
|
20
22
|
__exportStar(require("./library/lens/mod.js"), exports);
|
|
21
23
|
__exportStar(require("./library/namespace.js"), exports);
|
|
22
24
|
__exportStar(require("./library/engine/mod.js"), exports);
|
|
@@ -3,5 +3,5 @@ import { DataFactory, type RDF } from "./rdf.js";
|
|
|
3
3
|
import type { ExpandedSchema } from "./schema/mod.js";
|
|
4
4
|
type DecodedNode = Record<string, unknown>;
|
|
5
5
|
export declare const encode: (node: DecodedNode, schema: ExpandedSchema, options: Options, includeType?: boolean, variableInitCounter?: number) => RDF.Quad[];
|
|
6
|
-
export declare const encodeValue: (value: unknown, datatype: string, df: DataFactory) => RDF.Literal | import("rdf-data-factory").NamedNode<string>;
|
|
6
|
+
export declare const encodeValue: (value: unknown, datatype: string, df: DataFactory) => RDF.Literal | import("rdf-data-factory").Literal | import("rdf-data-factory").NamedNode<string>;
|
|
7
7
|
export {};
|
|
@@ -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";
|
|
@@ -2,8 +2,8 @@ import { xsd } from "../../namespaces/xsd.js";
|
|
|
2
2
|
import { rdf } from "../../namespaces/rdf.js";
|
|
3
3
|
import { ldkit } from "../../namespaces/ldkit.js";
|
|
4
4
|
import { type IRI } from "../rdf.js";
|
|
5
|
-
/** Map of
|
|
6
|
-
|
|
5
|
+
/** Map of default RDF data types and their JavaScript native counterparts */
|
|
6
|
+
type DefaultDataTypes = {
|
|
7
7
|
[xsd.dateTime]: Date;
|
|
8
8
|
[xsd.date]: Date;
|
|
9
9
|
[xsd.gDay]: Date;
|
|
@@ -42,5 +42,15 @@ export type SupportedDataTypes = {
|
|
|
42
42
|
[xsd.duration]: string;
|
|
43
43
|
[ldkit.IRI]: IRI;
|
|
44
44
|
};
|
|
45
|
+
/** Custom data types definition. Keys are type IRIs, values are JavaScript native types */
|
|
46
|
+
export interface CustomDataTypes {
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Map of supported RDF data types and their JavaScript native counterparts,
|
|
50
|
+
* combines default data types with custom data types.
|
|
51
|
+
* The keys are the IRIs of the data types, and the values are the corresponding JavaScript types.
|
|
52
|
+
*/
|
|
53
|
+
export type SupportedDataTypes = Omit<DefaultDataTypes, keyof CustomDataTypes> & CustomDataTypes;
|
|
45
54
|
/** List of supported native JavaScript types */
|
|
46
55
|
export type SupportedNativeTypes = SupportedDataTypes[keyof SupportedDataTypes];
|
|
56
|
+
export {};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type { SupportedDataTypes, SupportedNativeTypes } from "./data_types.js";
|
|
1
|
+
export type { CustomDataTypes, SupportedDataTypes, SupportedNativeTypes, } from "./data_types.js";
|
|
2
2
|
export type { Identity, SchemaInterface, SchemaSearchInterface, SchemaUpdateInterface, } from "./interface.js";
|
|
3
3
|
export type { ExpandedProperty, ExpandedSchema, Property, Schema, } from "./schema.js";
|
|
4
4
|
export type { SearchFilters, SearchSchema } from "./search.js";
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { RDF } from "./rdf.js";
|
|
2
|
+
import { SupportedDataTypes } from "./schema/mod.js";
|
|
3
|
+
/**
|
|
4
|
+
* Registers a data type handler for translating between RDF literals and JavaScript values.
|
|
5
|
+
*
|
|
6
|
+
* In order to register a custom data type handler, the custom data type TypeScript mapping needs
|
|
7
|
+
* to be added to the {@link CustomDataTypes} interface using module augmentation.
|
|
8
|
+
*
|
|
9
|
+
* Two handlers are required:
|
|
10
|
+
* 1) A function to translate from RDF literal value (string) to JavaScript value.
|
|
11
|
+
* 2) A function to translate from JavaScript value to RDF literal value (string).
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```typescript
|
|
15
|
+
* import { registerDataHandler } from "ldkit";
|
|
16
|
+
*
|
|
17
|
+
* const customNumberDataType = "http://example.org/number";
|
|
18
|
+
*
|
|
19
|
+
* declare module "ldkit" {
|
|
20
|
+
* interface CustomDataTypes {
|
|
21
|
+
* [customNumberDataType]: number;
|
|
22
|
+
* }
|
|
23
|
+
* }
|
|
24
|
+
*
|
|
25
|
+
* registerDataHandler(
|
|
26
|
+
* customNumberDataType,
|
|
27
|
+
* (literalValue: string) => parseInt(literalValue),
|
|
28
|
+
* (nativeValue: number) => nativeValue.toString(),
|
|
29
|
+
* );
|
|
30
|
+
* ```
|
|
31
|
+
*
|
|
32
|
+
* @param dataType - The data type to register.
|
|
33
|
+
* @param translateFromRDF - Function to translate from RDF literal to JavaScript value.
|
|
34
|
+
* @param translateToRDF - Function to translate from JavaScript value to RDF literal.
|
|
35
|
+
*/
|
|
36
|
+
export declare function registerDataHandler<T extends keyof SupportedDataTypes>(dataType: T, translateFromRDF: (literalValue: string) => SupportedDataTypes[T], translateToRDF: (nativeValue: SupportedDataTypes[T]) => string): void;
|
|
37
|
+
export declare function translateFromRdf(literal: RDF.Literal): any;
|
|
38
|
+
export declare function translateToRdf(value: unknown, dataType: keyof SupportedDataTypes | string): RDF.Literal | import("rdf-data-factory").Literal;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { readableFromWeb } from "readable-from-web";
|
package/types/mod.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export { type Options, setGlobalOptions } from "./library/options.js";
|
|
2
|
-
export type { Identity, Property, Schema, SchemaInterface, SchemaSearchInterface, SchemaUpdateInterface, SupportedDataTypes, } from "./library/schema/mod.js";
|
|
2
|
+
export type { CustomDataTypes, Identity, Property, Schema, SchemaInterface, SchemaSearchInterface, SchemaUpdateInterface, SupportedDataTypes, } from "./library/schema/mod.js";
|
|
3
|
+
export { registerDataHandler } from "./library/translator.js";
|
|
3
4
|
export * from "./library/lens/mod.js";
|
|
4
5
|
export * from "./library/namespace.js";
|
|
5
6
|
export * from "./library/engine/mod.js";
|