eyereasoner 1.0.2 → 1.1.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/README.md CHANGED
@@ -15,27 +15,106 @@ The simplest way to use this package is to execute a query over a dataset and ge
15
15
  import { basicQuery } from 'eyereasoner';
16
16
 
17
17
  async function main() {
18
- const resultQuads = await basicQuery(dataQuads, queryQuads);
18
+ const {
19
+ // The result of the query (as an array of quads)
20
+ result,
21
+ // The proof of the results (as an array of quads)
22
+ proof
23
+ } = await basicQuery(dataQuads, queryQuads);
19
24
  }
20
25
 
21
26
  main();
22
27
  ```
23
28
 
24
- Here the inputs and outputs are both arrays of RDF/JS Quads
29
+ Here the inputs and outputs are both arrays of RDF/JS Quads; for instance
30
+
31
+ ```ts
32
+ const queryQuads = [
33
+ DF.quad(
34
+ DF.namedNode('http://example.org/socrates#Socrates'),
35
+ DF.namedNode('http://www.w3.org/1999/02/22-rdf-syntax-ns#type'),
36
+ DF.variable('WHAT'),
37
+ DF.blankNode('b1')
38
+ ),
39
+ DF.quad(
40
+ DF.namedNode('http://example.org/socrates#Socrates'),
41
+ DF.namedNode('http://www.w3.org/1999/02/22-rdf-syntax-ns#type'),
42
+ DF.variable('WHAT'),
43
+ DF.blankNode('b2')
44
+ ),
45
+ DF.quad(
46
+ DF.blankNode('b1'),
47
+ DF.namedNode('http://www.w3.org/2000/10/swap/log#implies'),
48
+ DF.blankNode('b2')
49
+ )
50
+ ]
51
+
52
+ const dataQuads = [
53
+ DF.quad(
54
+ DF.namedNode('http://example.org/socrates#Socrates'),
55
+ DF.namedNode('http://www.w3.org/1999/02/22-rdf-syntax-ns#type'),
56
+ DF.namedNode('http://example.org/socrates#Human'),
57
+ ),
58
+ DF.quad(
59
+ DF.namedNode('http://example.org/socrates#Human'),
60
+ DF.namedNode('http://www.w3.org/2000/01/rdf-schema#subClassOf'),
61
+ DF.namedNode('http://example.org/socrates#Mortal'),
62
+ ),
63
+ DF.quad(
64
+ DF.variable('A'),
65
+ DF.namedNode('http://www.w3.org/2000/01/rdf-schema#subClassOf'),
66
+ DF.variable('B'),
67
+ DF.blankNode('b1')
68
+ ),
69
+ DF.quad(
70
+ DF.variable('S'),
71
+ DF.namedNode('http://www.w3.org/1999/02/22-rdf-syntax-ns#type'),
72
+ DF.variable('A'),
73
+ DF.blankNode('b1')
74
+ ),
75
+ DF.quad(
76
+ DF.variable('S'),
77
+ DF.namedNode('http://www.w3.org/1999/02/22-rdf-syntax-ns#type'),
78
+ DF.variable('B'),
79
+ DF.blankNode('b2')
80
+ ),
81
+ DF.quad(
82
+ DF.blankNode('b1'),
83
+ DF.namedNode('http://www.w3.org/2000/10/swap/log#implies'),
84
+ DF.blankNode('b2')
85
+ ),
86
+ ]
87
+ ```
25
88
 
26
89
  ## Advanced usage
27
90
 
28
91
  To have more granular control one can also use this module as follows
29
92
 
30
93
  ```ts
31
- import { SWIPL, loadEye } from 'eyereasoner';
94
+ import { SWIPL, loadEye, queryOnce } from 'eyereasoner';
95
+
96
+ const query = `
97
+ @prefix : <http://example.org/socrates#>.
98
+
99
+ {:Socrates a ?WHAT} => {:Socrates a ?WHAT}.
100
+ `
101
+
102
+ const data = `
103
+ @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>.
104
+ @prefix : <http://example.org/socrates#>.
105
+
106
+ :Socrates a :Human.
107
+ :Human rdfs:subClassOf :Mortal.
108
+
109
+ {?A rdfs:subClassOf ?B. ?S a ?A} => {?S a ?B}.
110
+ `
32
111
 
33
112
  async function main() {
34
113
  // Instantiate a new SWIPL module and log any results it produces to the console
35
114
  const Module = await SWIPL({ print: (str: string) => { console.log(str) }, arguments: ['-q'] });
36
115
 
37
116
  // Load EYE into the SWIPL Module and run consule("eye.pl").
38
- loadEye(MODULE)
117
+ loadEye(Module)
39
118
 
40
119
  // Load the the strings data and query as files data.n3 and query.n3 into the module
41
120
  Module.FS.writeFile('data.n3', data);
@@ -44,6 +123,9 @@ async function main() {
44
123
  // Execute main(['--quiet', './data.n3', '--query', './query.n3']).
45
124
  queryOnce(Module, 'main', ['--quiet', './data.n3', '--query', './query.n3']);
46
125
  }
126
+
127
+ main();
128
+
47
129
  ```
48
130
 
49
131
  ## License
package/dist/index.d.ts CHANGED
@@ -7,4 +7,7 @@ export { default as SWIPL } from './swipl-bundled.temp';
7
7
  * @param query The query as RDF/JS quads
8
8
  * @returns The result of the query as RDF/JS quads
9
9
  */
10
- export declare function basicQuery(data: Quad[], query: Quad[]): Promise<Quad[]>;
10
+ export declare function basicQuery(data: Quad[], query: Quad[]): Promise<{
11
+ result: Quad[];
12
+ proof: Quad[];
13
+ }>;
@@ -0,0 +1,12 @@
1
+ import { Quad, Term } from '@rdfjs/types';
2
+ import { Store } from 'n3';
3
+ export declare class N3Writer {
4
+ private _writer;
5
+ _encodePredicate(term: Term): string;
6
+ _encodeSubject(entity: Term, store: Store): string;
7
+ _encodeObject(entity: Term, store: Store): string;
8
+ quadToString(t: Quad, store: Store): string;
9
+ quadsStoreToString(store: Store, graph?: Term): string;
10
+ quadsToString(quads: Quad[]): string;
11
+ }
12
+ export declare function write(quads: Quad[]): string;
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.write = exports.N3Writer = void 0;
4
+ const n3_1 = require("n3");
5
+ function isQuoted(term, store) {
6
+ return term.termType === 'BlankNode' && store.getQuads(null, null, null, term).length > 0;
7
+ }
8
+ class N3Writer {
9
+ constructor() {
10
+ this._writer = new n3_1.Writer();
11
+ }
12
+ _encodePredicate(term) {
13
+ if (term.termType === 'NamedNode') {
14
+ switch (term.value) {
15
+ case 'http://www.w3.org/2000/10/swap/log#implies':
16
+ return '=>';
17
+ case 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type':
18
+ return 'a';
19
+ }
20
+ }
21
+ return this._writer._encodeIriOrBlank(term);
22
+ }
23
+ _encodeSubject(entity, store) {
24
+ if (isQuoted(entity, store)) {
25
+ return `{${this.quadsStoreToString(store, entity)}}`;
26
+ }
27
+ return this._writer._encodeSubject(entity);
28
+ }
29
+ _encodeObject(entity, store) {
30
+ if (isQuoted(entity, store)) {
31
+ return `{${this.quadsStoreToString(store, entity)}}`;
32
+ }
33
+ return this._writer._encodeObject(entity);
34
+ }
35
+ // ### `quadToString` serializes a quad as a string
36
+ quadToString(t, store) {
37
+ return `${this._encodeSubject(t.subject, store)} ${this._encodePredicate(t.predicate)} ${this._encodeObject(t.object, store)}`;
38
+ }
39
+ // ### `quadsToString` serializes an array of quads as a string
40
+ quadsStoreToString(store, graph = n3_1.DataFactory.defaultGraph()) {
41
+ return store.getQuads(null, null, null, graph)
42
+ .map(t => this.quadToString(t, store))
43
+ .join(' . ') + ' . ';
44
+ }
45
+ quadsToString(quads) {
46
+ return this.quadsStoreToString(new n3_1.Store(quads));
47
+ }
48
+ }
49
+ exports.N3Writer = N3Writer;
50
+ function write(quads) {
51
+ return (new N3Writer).quadsToString(quads);
52
+ }
53
+ exports.write = write;
@@ -45,4 +45,7 @@ export declare function executeBasicEyeQuery(swipl: typeof SWIPL, data: string,
45
45
  * @param queryString The query (in N3 format)
46
46
  * @returns The result of the query
47
47
  */
48
- export declare function executeBasicEyeQueryQuads(swipl: typeof SWIPL, data: Quad[], queryString: Quad[]): Promise<Quad[]>;
48
+ export declare function executeBasicEyeQueryQuads(swipl: typeof SWIPL, data: Quad[], queryString: Quad[]): Promise<{
49
+ result: Quad[];
50
+ proof: Quad[];
51
+ }>;
@@ -14,6 +14,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
15
  exports.executeBasicEyeQueryQuads = exports.executeBasicEyeQuery = exports.loadAndRunQuery = exports.runQuery = exports.loadEye = exports.queryOnce = exports.query = void 0;
16
16
  const n3_1 = require("n3");
17
+ const n3Writer_temp_1 = require("./n3Writer.temp");
17
18
  const eye_pl_1 = __importDefault(require("./eye.pl"));
18
19
  /**
19
20
  * Executes a query
@@ -53,9 +54,9 @@ exports.loadEye = loadEye;
53
54
  * @returns The same SWIPL module
54
55
  */
55
56
  function runQuery(Module, data, queryString) {
56
- Module.FS.writeFile('data.n3', data);
57
- Module.FS.writeFile('query.n3', queryString);
58
- queryOnce(Module, 'main', ['--quiet', './data.n3', '--query', './query.n3']);
57
+ Module.FS.writeFile('data.nq', data);
58
+ Module.FS.writeFile('query.nq', queryString);
59
+ queryOnce(Module, 'main', ['--quiet', './data.nq', '--query', './query.nq']);
59
60
  return Module;
60
61
  }
61
62
  exports.runQuery = runQuery;
@@ -78,7 +79,7 @@ exports.loadAndRunQuery = loadAndRunQuery;
78
79
  function executeBasicEyeQuery(swipl, data, queryString) {
79
80
  return __awaiter(this, void 0, void 0, function* () {
80
81
  let res = '';
81
- const Module = yield swipl({ print: (str) => { res += str; }, arguments: ['-q'] });
82
+ const Module = yield swipl({ print: (str) => { res += `${str}\n`; }, arguments: ['-q'] });
82
83
  loadAndRunQuery(Module, data, queryString);
83
84
  return res;
84
85
  });
@@ -92,9 +93,24 @@ exports.executeBasicEyeQuery = executeBasicEyeQuery;
92
93
  */
93
94
  function executeBasicEyeQueryQuads(swipl, data, queryString) {
94
95
  return __awaiter(this, void 0, void 0, function* () {
95
- const parser = new n3_1.Parser();
96
- const writer = new n3_1.Writer();
97
- return parser.parse(yield executeBasicEyeQuery(swipl, writer.quadsToString(data), writer.quadsToString(queryString)));
96
+ const parser = new n3_1.Parser({ format: 'text/n3' });
97
+ const queryResult = yield executeBasicEyeQuery(swipl, (0, n3Writer_temp_1.write)(data), (0, n3Writer_temp_1.write)(queryString));
98
+ const proof = parser.parse(queryResult);
99
+ const store = new n3_1.Store(proof);
100
+ const proofNode = store.getSubjects('http://www.w3.org/1999/02/22-rdf-syntax-ns#type', 'http://www.w3.org/2000/10/swap/reason#Proof', n3_1.DataFactory.defaultGraph());
101
+ if (proofNode.length !== 1) {
102
+ throw new Error(`Expected exactly one proof: received ${proofNode.length}`);
103
+ }
104
+ const results = store.getObjects(proofNode[0], 'http://www.w3.org/2000/10/swap/reason#gives', n3_1.DataFactory.defaultGraph());
105
+ if (results.length !== 1) {
106
+ throw new Error(`Expected exactly one triple giving inference results from proof: received ${results.length}`);
107
+ }
108
+ const result = store.getQuads(null, null, null, results[0])
109
+ .map((res) => n3_1.DataFactory.quad(res.subject, res.predicate, res.object));
110
+ return {
111
+ proof,
112
+ result,
113
+ };
98
114
  });
99
115
  }
100
116
  exports.executeBasicEyeQueryQuads = executeBasicEyeQueryQuads;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eyereasoner",
3
- "version": "1.0.2",
3
+ "version": "1.1.0",
4
4
  "description": "Distributing the [EYE](https://github.com/josd/eye) reasoner for browser and node using WebAssembly.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.js",
@@ -60,6 +60,7 @@
60
60
  "eslint-config-airbnb-base": "^15.0.0",
61
61
  "eslint-plugin-import": "^2.26.0",
62
62
  "jest": "^29.3.1",
63
+ "jest-rdf": "^1.7.1",
63
64
  "pre-commit": "^1.2.2",
64
65
  "rollup": "^3.8.1",
65
66
  "rollup-plugin-string": "^3.0.0",