eyeling 1.18.0 → 1.18.1

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/HANDBOOK.md CHANGED
@@ -1767,7 +1767,41 @@ For fully stream-oriented RDF/JS consumers there is also `reasonRdfJs(...)`, whi
1767
1767
 
1768
1768
  Eyeling exposes itself in three layers.
1769
1769
 
1770
- ### 14.1 The bundled CLI (`eyeling.js`)
1770
+ ### 14.1 Install and first run
1771
+
1772
+ Eyeling targets modern JavaScript runtimes. For the npm package and CLI workflow, use **Node.js 18 or newer**.
1773
+
1774
+ Install from npm:
1775
+
1776
+ ```bash
1777
+ npm i eyeling
1778
+ ```
1779
+
1780
+ Run a file:
1781
+
1782
+ ```bash
1783
+ npx eyeling examples/socrates.n3
1784
+ ```
1785
+
1786
+ Show the available options:
1787
+
1788
+ ```bash
1789
+ npx eyeling --help
1790
+ ```
1791
+
1792
+ A few practical defaults are worth remembering:
1793
+
1794
+ - In normal mode, Eyeling prints **newly derived forward facts**.
1795
+ - If the input contains top-level `log:query` directives, Eyeling prints the **query-selected conclusion triples** instead.
1796
+ - If the final closure contains any `log:outputString` triples, Eyeling renders those strings instead of emitting the default N3 result set.
1797
+
1798
+ Custom builtins can be loaded explicitly from the CLI:
1799
+
1800
+ ```bash
1801
+ npx eyeling --builtin lib/builtin-sudoku.js examples/sudoku.n3
1802
+ ```
1803
+
1804
+ ### 14.2 The bundled CLI (`eyeling.js`)
1771
1805
 
1772
1806
  The bundle contains the whole engine. The CLI path is the “canonical behavior”:
1773
1807
 
@@ -1777,7 +1811,7 @@ The bundle contains the whole engine. The CLI path is the “canonical behavior
1777
1811
  - optional proof comments
1778
1812
  - optional streaming
1779
1813
 
1780
- #### 14.1.1 CLI options at a glance
1814
+ #### 14.2.1 CLI options at a glance
1781
1815
 
1782
1816
  The current CLI supports a small set of flags (see `lib/cli.js`):
1783
1817
 
@@ -1790,7 +1824,7 @@ The current CLI supports a small set of flags (see `lib/cli.js`):
1790
1824
  - `-v`, `--version` — print version and exit.
1791
1825
  - `-h`, `--help` — show usage.
1792
1826
 
1793
- ### 14.2 `lib/entry.js`: bundler-friendly exports
1827
+ ### 14.3 `lib/entry.js`: bundler-friendly exports
1794
1828
 
1795
1829
  `lib/entry.js` exports:
1796
1830
 
@@ -1799,7 +1833,7 @@ The current CLI supports a small set of flags (see `lib/cli.js`):
1799
1833
 
1800
1834
  `rdfjs` is a small built-in RDF/JS `DataFactory`, so browser / worker code can construct quads without pulling in another package first.
1801
1835
 
1802
- ### 14.3 `index.js`: the npm API wrapper
1836
+ ### 14.4 `index.js`: the npm API wrapper
1803
1837
 
1804
1838
  The npm `reason(...)` function does something intentionally simple and robust:
1805
1839
 
@@ -1820,6 +1854,106 @@ For structured JavaScript input, rules are supplied as current Eyeling `Rule` /
1820
1854
 
1821
1855
  If you want to use N3 source text, pass the whole input as a plain N3 string.
1822
1856
 
1857
+ #### 14.4.1 RDF/JS quads as fact input
1858
+
1859
+ Eyeling can take RDF/JS quads directly as its fact input. At the npm API boundary, the input object may provide any of:
1860
+
1861
+ - `quads`
1862
+ - `facts`
1863
+ - `dataset`
1864
+
1865
+ Each is treated as an iterable of RDF/JS **default-graph** quads and converted into Eyeling’s internal triple form before reasoning starts.
1866
+
1867
+ ```js
1868
+ const { reason, rdfjs } = require('eyeling');
1869
+
1870
+ const input = {
1871
+ quads: [
1872
+ rdfjs.quad(
1873
+ rdfjs.namedNode('http://example.org/Socrates'),
1874
+ rdfjs.namedNode('http://www.w3.org/1999/02/22-rdf-syntax-ns#type'),
1875
+ rdfjs.namedNode('http://example.org/Human'),
1876
+ ),
1877
+ ],
1878
+ n3: `
1879
+ @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>.
1880
+ @prefix : <http://example.org/>.
1881
+ :Human rdfs:subClassOf :Mortal.
1882
+ { ?x a ?c. ?c rdfs:subClassOf ?d. } => { ?x a ?d. }.
1883
+ `,
1884
+ };
1885
+
1886
+ const out = reason(input);
1887
+ ```
1888
+
1889
+ The important point is architectural: RDF/JS quads can be used as the **fact channel**, while rules may still come from N3 text or Eyeling rule objects. Named-graph quads are intentionally rejected here; Eyeling’s input model is triple-oriented and expects the default graph only.
1890
+
1891
+ #### 14.4.2 Passing Eyeling rule objects directly
1892
+
1893
+ The JS API also accepts Eyeling rule objects directly, so you do not have to serialize everything back into N3 first.
1894
+
1895
+ That means an input such as this is valid:
1896
+
1897
+ ```js
1898
+ const { reason } = require('eyeling');
1899
+
1900
+ const input = {
1901
+ triples: [
1902
+ /* Eyeling Triple objects */
1903
+ ],
1904
+ forwardRules: [
1905
+ /* Eyeling Rule objects */
1906
+ ],
1907
+ backwardRules: [
1908
+ /* optional Eyeling Rule objects */
1909
+ ],
1910
+ };
1911
+
1912
+ const out = reason(input);
1913
+ ```
1914
+
1915
+ The accepted shapes are intentionally flexible:
1916
+
1917
+ - `triples`
1918
+ - `forwardRules` or `frules`
1919
+ - `backwardRules` or `brules`
1920
+ - `queryRules`, `logQueryRules`, or `qrules`
1921
+ - a full AST bundle like `[prefixes, triples, frules, brules, queryRules]`
1922
+
1923
+ So Eyeling rule objects can be passed directly in the API, either as separate arrays or bundled into the same object graph the parser itself uses.
1924
+
1925
+ #### 14.4.3 Consuming derived RDF/JS results
1926
+
1927
+ There are two main ways to consume derived results in RDF/JS form.
1928
+
1929
+ First, `reasonStream(...)` can emit RDF/JS quads **while reasoning runs**. Pass `rdfjs: true` and an `onDerived(...)` callback:
1930
+
1931
+ ```js
1932
+ const { reasonStream } = require('eyeling/lib/entry');
1933
+
1934
+ reasonStream(input, {
1935
+ rdfjs: true,
1936
+ onDerived({ triple, quad }) {
1937
+ // triple = Eyeling's N3 string form
1938
+ // quad = RDF/JS Quad for the same derived fact
1939
+ },
1940
+ });
1941
+ ```
1942
+
1943
+ This is the “push” interface: each newly derived forward fact is reported as soon as it is produced.
1944
+
1945
+ Second, `reasonRdfJs(...)` exposes the same derived results as an **async stream of RDF/JS quads**:
1946
+
1947
+ ```js
1948
+ const { reasonRdfJs } = require('eyeling/lib/entry');
1949
+
1950
+ for await (const quad of reasonRdfJs(input)) {
1951
+ // consume RDF/JS quads incrementally
1952
+ }
1953
+ ```
1954
+
1955
+ This is the “pull” interface: the consumer iterates an async iterable of quads instead of registering a callback.
1956
+
1823
1957
  One practical implication remains:
1824
1958
 
1825
1959
  - if you want _in-process_ access to the engine objects (facts arrays, derived proof objects), use `reasonStream` / `reasonRdfJs` from the bundle entry rather than the subprocess-based API.
package/README.md CHANGED
@@ -4,218 +4,16 @@
4
4
 
5
5
  A compact [Notation3 (N3)](https://notation3.org/) reasoner in **JavaScript**.
6
6
 
7
- - Single self-contained bundle (`eyeling.js`), no external runtime dependencies
8
- - Forward (`=>`) and backward (`<=`) chaining over Horn-style rules
9
- - **CLI / npm `reason()` output is mode-dependent by default**: it prints **newly derived forward facts** in normal mode, or (when top-level `{ ... } log:query { ... }.` directives are present) the **unique instantiated conclusion triples** of those queries, optionally with compact proof comments
10
- - Works in Node.js and fully client-side (browser/worker)
11
-
12
- ## Links
13
-
14
- - **Handbook:** [https://eyereasoner.github.io/eyeling/HANDBOOK](https://eyereasoner.github.io/eyeling/HANDBOOK)
15
- - **Semantics:** [https://eyereasoner.github.io/eyeling/SEMANTICS](https://eyereasoner.github.io/eyeling/SEMANTICS)
16
- - **Playground:** [https://eyereasoner.github.io/eyeling/demo](https://eyereasoner.github.io/eyeling/demo)
17
- - **Conformance report:** [https://codeberg.org/phochste/notation3tests/src/branch/main/reports/report.md](https://codeberg.org/phochste/notation3tests/src/branch/main/reports/report.md)
18
-
19
- Eyeling is regularly checked against the community Notation3 test suite. If you want implementation details (parser, unifier, proof search, skolemization, scoped closure, builtins), start with the handbook.
20
-
21
7
  ## Quick start
22
8
 
23
- ### Requirements
24
-
25
- - Node.js >= 18
26
-
27
- ### Install
28
-
29
9
  ```bash
30
10
  npm i eyeling
31
- ```
32
-
33
- ## CLI usage
34
-
35
- Run on a file:
36
-
37
- ```bash
38
11
  npx eyeling examples/socrates.n3
39
12
  ```
40
13
 
41
- Show all options:
42
-
43
- ```bash
44
- npx eyeling --help
45
- ```
46
-
47
- Useful flags include `--proof-comments`, `--stream`, and `--enforce-https`. If the final closure contains any `log:outputString` triples, Eyeling now renders those strings automatically instead of printing N3 output.
48
-
49
- ## What gets printed?
50
-
51
- ### Normal mode (default)
52
-
53
- Without top-level `log:query` directives, Eyeling prints **newly derived forward facts** by default.
54
-
55
- ### `log:query` mode (output selection)
56
-
57
- If the input contains one or more **top-level** directives of the form:
58
-
59
- ```n3
60
- { ?x a :Human. } log:query { ?x a :Mortal. }.
61
- ```
62
-
63
- Eyeling still computes the saturated forward closure, but it **prints only** the **unique instantiated conclusion triples** of those `log:query` directives (instead of all newly derived forward facts).
64
-
65
- ## JavaScript API
66
-
67
- ### npm helper: `reason()`
68
-
69
- CommonJS:
70
-
71
- ```js
72
- const { reason } = require('eyeling');
73
-
74
- const input = `
75
- @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>.
76
- @prefix : <http://example.org/socrates#>.
77
-
78
- :Socrates a :Human.
79
- :Human rdfs:subClassOf :Mortal.
80
-
81
- { ?s a ?A. ?A rdfs:subClassOf ?B. } => { ?s a ?B. }.
82
- `;
83
-
84
- console.log(reason({ proofComments: false }, input));
85
- ```
86
-
87
- ESM:
88
-
89
- ```js
90
- import eyeling from 'eyeling';
91
-
92
- console.log(eyeling.reason({ proofComments: false }, input));
93
- ```
94
-
95
- Notes:
96
-
97
- - `reason()` returns the same textual output you would get from the CLI for the same input/options.
98
- - By default, the npm helper keeps output machine-friendly (`proofComments: false`).
99
- - The npm helper shells out to the bundled `eyeling.js` CLI for simplicity and robustness.
100
-
101
- ### RDF/JS and Eyeling rule-object interop
102
-
103
- The JavaScript APIs now accept three input styles:
104
-
105
- 1. plain N3 text
106
- 2. RDF/JS facts (`quads`, `facts`, or `dataset`)
107
- 3. Eyeling rule objects / AST bundles (the same shapes you get from `eyeling --ast`)
108
-
109
- If you want to use N3 source text, pass the whole input as a plain N3 string.
110
-
111
- For RDF/JS facts, the graph must be the default graph. Named-graph quads are rejected.
112
-
113
- For structured inputs, `rules` is supplied as current Eyeling rule objects:
114
-
115
- ```js
116
- const { reason, rdfjs } = require('eyeling');
117
-
118
- const ex = 'http://example.org/';
119
-
120
- const rule = {
121
- _type: 'Rule',
122
- premise: [
123
- {
124
- _type: 'Triple',
125
- s: { _type: 'Var', name: 'x' },
126
- p: { _type: 'Iri', value: ex + 'parent' },
127
- o: { _type: 'Var', name: 'y' },
128
- },
129
- ],
130
- conclusion: [
131
- {
132
- _type: 'Triple',
133
- s: { _type: 'Var', name: 'x' },
134
- p: { _type: 'Iri', value: ex + 'ancestor' },
135
- o: { _type: 'Var', name: 'y' },
136
- },
137
- ],
138
- isForward: true,
139
- isFuse: false,
140
- headBlankLabels: [],
141
- };
142
-
143
- const out = reason(
144
- { proofComments: false },
145
- {
146
- quads: [rdfjs.quad(rdfjs.namedNode(ex + 'alice'), rdfjs.namedNode(ex + 'parent'), rdfjs.namedNode(ex + 'bob'))],
147
- rules: [rule],
148
- },
149
- );
150
- ```
151
-
152
- You can also pass a full AST bundle directly:
153
-
154
- ```js
155
- const ast = [prefixes, triples, forwardRules, backwardRules];
156
- const out2 = reason({ proofComments: false }, ast);
157
- ```
158
-
159
- ### Direct bundle / browser-worker API: `reasonStream()`
160
-
161
- For in-process reasoning (browser, worker, or direct use of `eyeling.js`):
162
-
163
- ```js
164
- const result = eyeling.reasonStream(input, {
165
- proof: false,
166
- onDerived: ({ triple }) => console.log(triple),
167
- // includeInputFactsInClosure: false,
168
- });
169
-
170
- console.log(result.closureN3);
171
- ```
172
-
173
- `eyeling.js` now also exposes `eyeling.rdfjs` and `eyeling.reasonRdfJs(...)` for RDF/JS workflows.
174
-
175
- #### `reasonStream()` output behavior
176
-
177
- `closureN3` is also mode-dependent:
178
-
179
- - **Normal mode:** by default, `closureN3` is the closure (**input facts + derived facts**)
180
- - **`log:query` mode:** `closureN3` is the **query-selected triples**
181
-
182
- To exclude input facts from the normal-mode closure, pass:
183
-
184
- ```js
185
- includeInputFactsInClosure: false;
186
- ```
187
-
188
- When `rdfjs: true` is passed, `onDerived` also receives a `quad` field and the result may include `closureQuads` / `queryQuads`.
189
-
190
- The returned object also includes `queryMode`, `queryTriples`, and `queryDerived` (and in normal mode, `onDerived` fires for newly derived facts; in `log:query` mode it fires for the query-selected derived triples).
191
-
192
- ### `reasonRdfJs()`
193
-
194
- `reasonRdfJs(input, opts)` exposes derived results as an async iterable of RDF/JS quads as they are produced:
195
-
196
- ```js
197
- const { reasonRdfJs, rdfjs } = require('eyeling');
198
-
199
- for await (const quad of reasonRdfJs({
200
- quads: [rdfjs.quad(rdfjs.namedNode(ex + 'alice'), rdfjs.namedNode(ex + 'parent'), rdfjs.namedNode(ex + 'bob'))],
201
- rules: [rule],
202
- })) {
203
- console.log(quad.subject.value, quad.predicate.value, quad.object.value);
204
- }
205
- ```
206
-
207
- ## Builtins
208
-
209
- Builtins are defined in [eyeling-builtins.ttl](https://github.com/eyereasoner/eyeling/blob/main/eyeling-builtins.ttl) and described in the [Handbook (Chapter 11)](https://eyereasoner.github.io/eyeling/HANDBOOK#ch11).
210
-
211
- ## Development and testing (repo checkout)
212
-
213
- ```bash
214
- npm test
215
- ```
216
-
217
- You can also inspect the `examples/` directory for many small and large N3 programs.
218
-
219
- ## License
14
+ ## Read more
220
15
 
221
- MIT see [LICENSE.md](https://github.com/eyereasoner/eyeling/blob/main/LICENSE.md).
16
+ - **Handbook:** [eyereasoner.github.io/eyeling/HANDBOOK](https://eyereasoner.github.io/eyeling/HANDBOOK)
17
+ - **Semantics:** [eyereasoner.github.io/eyeling/SEMANTICS](https://eyereasoner.github.io/eyeling/SEMANTICS)
18
+ - **Playground:** [eyereasoner.github.io/eyeling/demo](https://eyereasoner.github.io/eyeling/demo)
19
+ - **Conformance report:** [codeberg.org/phochste/notation3tests/.../report.md](https://codeberg.org/phochste/notation3tests/src/branch/main/reports/report.md)
@@ -115,7 +115,7 @@
115
115
  log:outputString "\n" ;
116
116
  log:outputString "Completed grid\n" ;
117
117
  log:outputString ?solutionText ;
118
- log:outputString "\n" .
118
+ log:outputString "\n\n" .
119
119
  :02-reason log:outputString "=== Reason Why ===\n" ;
120
120
  log:outputString ?reasonText ;
121
121
  log:outputString "\n\n" .
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eyeling",
3
- "version": "1.18.0",
3
+ "version": "1.18.1",
4
4
  "description": "A minimal Notation3 (N3) reasoner in JavaScript.",
5
5
  "main": "./index.js",
6
6
  "keywords": [