eyeling 1.27.9 → 1.28.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/README.md +3 -0
- package/dist/browser/eyeling.browser.js +313 -71
- package/examples/alma-rdf-messages.n3 +202 -0
- package/examples/output/alma-rdf-messages.n3 +0 -0
- package/eyeling.js +320 -72
- package/index.d.ts +3 -2
- package/lib/cli.js +140 -27
- package/lib/engine.js +31 -19
- package/lib/rdfjs.js +142 -25
- package/notes/rdf-message-logs.md +228 -0
- package/notes/rdfjs-integration.md +378 -0
- package/package.json +1 -1
- package/test/api.test.js +75 -20
- package/test/stream_messages.test.js +102 -3
- package/tools/bundle.js +7 -1
package/lib/cli.js
CHANGED
|
@@ -8,10 +8,13 @@
|
|
|
8
8
|
'use strict';
|
|
9
9
|
|
|
10
10
|
const fs = require('node:fs');
|
|
11
|
-
const os = require('node:os');
|
|
12
11
|
const path = require('node:path');
|
|
13
|
-
const { pathToFileURL, fileURLToPath } = require('node:url');
|
|
12
|
+
const { pathToFileURL, fileURLToPath, URL } = require('node:url');
|
|
14
13
|
const { TextDecoder } = require('node:util');
|
|
14
|
+
const http = require('node:http');
|
|
15
|
+
const https = require('node:https');
|
|
16
|
+
const readline = require('node:readline');
|
|
17
|
+
const zlib = require('node:zlib');
|
|
15
18
|
|
|
16
19
|
const engine = require('./engine');
|
|
17
20
|
const deref = require('./deref');
|
|
@@ -145,7 +148,8 @@ function __httpFetchScriptBody({ prefixOnly = false } = {}) {
|
|
|
145
148
|
if (finished) return;
|
|
146
149
|
chunks.push(chunk);
|
|
147
150
|
bytes += chunk.length;
|
|
148
|
-
|
|
151
|
+
const text = Buffer.concat(chunks, bytes).toString('utf8');
|
|
152
|
+
if (bytes >= limit || /^\\s*(?:@version|VERSION)\\s+(["'])(?:1\\.1|1\\.2|1\\.2-basic)-messages\\1\\s*\\.?\\s*(?:#.*)?$/im.test(text)) finish();
|
|
149
153
|
});
|
|
150
154
|
body.on('end', finish);
|
|
151
155
|
body.on('error', (e) => { console.error(e && e.message ? e.message : String(e)); process.exit(5); });
|
|
@@ -174,22 +178,95 @@ function __readHttpPrefixSync(sourceLabel, byteLimit = 64 * 1024) {
|
|
|
174
178
|
return r.stdout;
|
|
175
179
|
}
|
|
176
180
|
|
|
177
|
-
function
|
|
178
|
-
const
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
181
|
+
function __openHttpTextStream(sourceLabel, redirects = 0) {
|
|
182
|
+
const maxRedirects = 10;
|
|
183
|
+
return new Promise((resolve, reject) => {
|
|
184
|
+
if (redirects > maxRedirects) {
|
|
185
|
+
reject(new Error('Too many redirects'));
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
let parsed;
|
|
190
|
+
try {
|
|
191
|
+
parsed = new URL(sourceLabel);
|
|
192
|
+
} catch (e) {
|
|
193
|
+
reject(e);
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
const mod = parsed.protocol === 'https:' ? https : parsed.protocol === 'http:' ? http : null;
|
|
198
|
+
if (!mod) {
|
|
199
|
+
reject(new Error(`Unsupported protocol ${parsed.protocol}`));
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
const req = mod.request(
|
|
204
|
+
{
|
|
205
|
+
protocol: parsed.protocol,
|
|
206
|
+
hostname: parsed.hostname,
|
|
207
|
+
port: parsed.port || undefined,
|
|
208
|
+
path: parsed.pathname + parsed.search,
|
|
209
|
+
headers: {
|
|
210
|
+
accept: 'text/n3, text/turtle, application/trig, application/n-triples, application/n-quads, text/plain;q=0.8, */*;q=0.01',
|
|
211
|
+
'accept-encoding': 'identity',
|
|
212
|
+
'user-agent': 'eyeling-rdf-message-stream',
|
|
213
|
+
},
|
|
214
|
+
},
|
|
215
|
+
(res) => {
|
|
216
|
+
const sc = res.statusCode || 0;
|
|
217
|
+
if (sc >= 300 && sc < 400 && res.headers && res.headers.location) {
|
|
218
|
+
const next = new URL(res.headers.location, sourceLabel).toString();
|
|
219
|
+
res.resume();
|
|
220
|
+
resolve(__openHttpTextStream(next, redirects + 1));
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
if (sc < 200 || sc >= 300) {
|
|
224
|
+
res.resume();
|
|
225
|
+
reject(new Error(`HTTP status ${sc}`));
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
const enc = String((res.headers && res.headers['content-encoding']) || '').toLowerCase();
|
|
230
|
+
let body = res;
|
|
231
|
+
if (enc.includes('gzip')) body = res.pipe(zlib.createGunzip());
|
|
232
|
+
else if (enc.includes('deflate')) body = res.pipe(zlib.createInflate());
|
|
233
|
+
else if (enc.includes('br')) body = res.pipe(zlib.createBrotliDecompress());
|
|
234
|
+
resolve(body);
|
|
235
|
+
},
|
|
236
|
+
);
|
|
237
|
+
req.on('error', reject);
|
|
238
|
+
req.end();
|
|
185
239
|
});
|
|
186
|
-
if (r.status !== 0) {
|
|
187
|
-
try { fs.rmSync(dir, { recursive: true, force: true }); } catch {}
|
|
188
|
-
throw new Error(`Failed to dereference ${sourceLabel}${r.stderr ? ': ' + String(r.stderr).trim() : ''}`);
|
|
189
|
-
}
|
|
190
|
-
return { file, cleanup: () => { try { fs.rmSync(dir, { recursive: true, force: true }); } catch {} } };
|
|
191
240
|
}
|
|
192
241
|
|
|
242
|
+
async function forEachLineInHttpSource(sourceLabel, onLine) {
|
|
243
|
+
const body = await __openHttpTextStream(sourceLabel);
|
|
244
|
+
await new Promise((resolve, reject) => {
|
|
245
|
+
let settled = false;
|
|
246
|
+
function done(err) {
|
|
247
|
+
if (settled) return;
|
|
248
|
+
settled = true;
|
|
249
|
+
if (err) reject(err);
|
|
250
|
+
else resolve();
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
const rl = readline.createInterface({ input: body, crlfDelay: Infinity });
|
|
254
|
+
rl.on('line', (line) => {
|
|
255
|
+
try {
|
|
256
|
+
onLine(line + '\n');
|
|
257
|
+
} catch (e) {
|
|
258
|
+
try { rl.close(); } catch {}
|
|
259
|
+
if (body && typeof body.destroy === 'function') {
|
|
260
|
+
try { body.destroy(); } catch {}
|
|
261
|
+
}
|
|
262
|
+
done(e);
|
|
263
|
+
}
|
|
264
|
+
});
|
|
265
|
+
rl.on('close', () => done());
|
|
266
|
+
rl.on('error', done);
|
|
267
|
+
body.on('error', done);
|
|
268
|
+
});
|
|
269
|
+
}
|
|
193
270
|
|
|
194
271
|
const RDF_MESSAGE_VERSION_RE = /^\s*(?:@version|VERSION)\s+(["'])(?:1\.1|1\.2|1\.2-basic)-messages\1\s*\.?\s*(?:#.*)?$/im;
|
|
195
272
|
const RDF_MESSAGE_VERSION_LINE_RE = /^\s*(?:@version|VERSION)\s+(["'])(?:1\.1|1\.2|1\.2-basic)-messages\1\s*\.?\s*(?:#.*)?$/i;
|
|
@@ -407,15 +484,50 @@ function __forEachRdfMessageChunkSync(sourceLabel, onMessage) {
|
|
|
407
484
|
return;
|
|
408
485
|
}
|
|
409
486
|
if (__isHttpSource(sourceLabel)) {
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
487
|
+
throw new Error('internal error: HTTP RDF Message Logs must be streamed asynchronously');
|
|
488
|
+
}
|
|
489
|
+
forEachRdfMessageChunkInText(__readInputSourceSync(sourceLabel), onMessage);
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
|
|
493
|
+
async function forEachRdfMessageChunkInHttpSource(sourceLabel, onMessage) {
|
|
494
|
+
const directives = [];
|
|
495
|
+
const seenDirectives = new Set();
|
|
496
|
+
let chunk = '';
|
|
497
|
+
let messageIndex = 1;
|
|
498
|
+
let sawVersion = false;
|
|
499
|
+
let sawDelimiter = false;
|
|
500
|
+
|
|
501
|
+
function emit() {
|
|
502
|
+
onMessage({ messageIndex, chunk, directives: directives.slice() });
|
|
503
|
+
messageIndex += 1;
|
|
504
|
+
chunk = '';
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
await forEachLineInHttpSource(sourceLabel, (line) => {
|
|
508
|
+
if (RDF_MESSAGE_VERSION_LINE_RE.test(line)) {
|
|
509
|
+
sawVersion = true;
|
|
510
|
+
return;
|
|
511
|
+
}
|
|
512
|
+
if (RDF_MESSAGE_DELIMITER_LINE_RE.test(line)) {
|
|
513
|
+
emit();
|
|
514
|
+
sawDelimiter = true;
|
|
515
|
+
return;
|
|
415
516
|
}
|
|
517
|
+
addRdfDirective(directives, seenDirectives, line);
|
|
518
|
+
chunk += line;
|
|
519
|
+
});
|
|
520
|
+
|
|
521
|
+
if (!sawVersion) throw new Error('not an RDF Message Log: missing VERSION "*-messages" directive');
|
|
522
|
+
if (sawDelimiter || hasRdfPayload(chunk)) emit();
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
async function __forEachRdfMessageChunk(sourceLabel, onMessage) {
|
|
526
|
+
if (__isHttpSource(sourceLabel)) {
|
|
527
|
+
await forEachRdfMessageChunkInHttpSource(sourceLabel, onMessage);
|
|
416
528
|
return;
|
|
417
529
|
}
|
|
418
|
-
|
|
530
|
+
__forEachRdfMessageChunkSync(sourceLabel, onMessage);
|
|
419
531
|
}
|
|
420
532
|
|
|
421
533
|
function factsContainOutputStrings(triplesForOutput) {
|
|
@@ -481,7 +593,7 @@ function runParsedDocumentOnce(mergedDocument, { rdfMode = false, outputPrefixes
|
|
|
481
593
|
}
|
|
482
594
|
}
|
|
483
595
|
|
|
484
|
-
function runStreamMessagesMode(sourceLabels, { rdfMode }) {
|
|
596
|
+
async function runStreamMessagesMode(sourceLabels, { rdfMode }) {
|
|
485
597
|
const ordinarySourceLabels = [];
|
|
486
598
|
const messageSourceLabels = [];
|
|
487
599
|
|
|
@@ -533,7 +645,7 @@ function runStreamMessagesMode(sourceLabels, { rdfMode }) {
|
|
|
533
645
|
const fullIriPrefixes = new PrefixEnv({});
|
|
534
646
|
for (const messageSourceLabel of messageSourceLabels) {
|
|
535
647
|
try {
|
|
536
|
-
|
|
648
|
+
await __forEachRdfMessageChunk(messageSourceLabel, ({ messageIndex, chunk, directives }) => {
|
|
537
649
|
const messageText = buildSingleMessageReplayDocument({
|
|
538
650
|
sourceLabel: messageSourceLabel,
|
|
539
651
|
messageIndex,
|
|
@@ -567,7 +679,7 @@ function runStreamMessagesMode(sourceLabels, { rdfMode }) {
|
|
|
567
679
|
}
|
|
568
680
|
}
|
|
569
681
|
|
|
570
|
-
function main() {
|
|
682
|
+
async function main() {
|
|
571
683
|
// Drop "node" and script name; keep only user-provided args
|
|
572
684
|
// Expand combined short options: -pt == -p -t
|
|
573
685
|
const argvRaw = process.argv.slice(2);
|
|
@@ -706,7 +818,7 @@ function main() {
|
|
|
706
818
|
}
|
|
707
819
|
|
|
708
820
|
if (streamMessagesMode) {
|
|
709
|
-
runStreamMessagesMode(sourceLabels, { rdfMode });
|
|
821
|
+
await runStreamMessagesMode(sourceLabels, { rdfMode });
|
|
710
822
|
return;
|
|
711
823
|
}
|
|
712
824
|
|
|
@@ -790,7 +902,8 @@ function main() {
|
|
|
790
902
|
return false;
|
|
791
903
|
}
|
|
792
904
|
|
|
793
|
-
|
|
905
|
+
|
|
906
|
+
function factsContainOutputStrings(triplesForOutput) {
|
|
794
907
|
return (
|
|
795
908
|
Array.isArray(triplesForOutput) &&
|
|
796
909
|
triplesForOutput.some(
|
package/lib/engine.js
CHANGED
|
@@ -95,7 +95,7 @@ const {
|
|
|
95
95
|
} = require('./printing');
|
|
96
96
|
const {
|
|
97
97
|
getDataFactory,
|
|
98
|
-
|
|
98
|
+
internalTripleToRdfJsQuads,
|
|
99
99
|
normalizeParsedReasonerInputSync,
|
|
100
100
|
normalizeReasonerInputSync,
|
|
101
101
|
normalizeReasonerInputAsync,
|
|
@@ -3593,15 +3593,22 @@ function isUnsupportedRdfJsConversionError(err) {
|
|
|
3593
3593
|
);
|
|
3594
3594
|
}
|
|
3595
3595
|
|
|
3596
|
-
function
|
|
3596
|
+
function maybeTripleToRdfJsQuads(triple, rdfFactory, skipUnsupportedRdfJs) {
|
|
3597
3597
|
try {
|
|
3598
|
-
return
|
|
3598
|
+
return internalTripleToRdfJsQuads(triple, rdfFactory);
|
|
3599
3599
|
} catch (err) {
|
|
3600
|
-
if (skipUnsupportedRdfJs && isUnsupportedRdfJsConversionError(err)) return
|
|
3600
|
+
if (skipUnsupportedRdfJs && isUnsupportedRdfJsConversionError(err)) return [];
|
|
3601
3601
|
throw err;
|
|
3602
3602
|
}
|
|
3603
3603
|
}
|
|
3604
3604
|
|
|
3605
|
+
function addRdfJsPayloadQuads(payload, quads) {
|
|
3606
|
+
if (!Array.isArray(quads) || quads.length === 0) return payload;
|
|
3607
|
+
payload.quads = quads;
|
|
3608
|
+
if (quads.length === 1) payload.quad = quads[0];
|
|
3609
|
+
return payload;
|
|
3610
|
+
}
|
|
3611
|
+
|
|
3605
3612
|
function reasonStream(input, opts = {}) {
|
|
3606
3613
|
const {
|
|
3607
3614
|
baseIri = null,
|
|
@@ -3629,7 +3636,8 @@ function reasonStream(input, opts = {}) {
|
|
|
3629
3636
|
rdf: useRdfCompatibility,
|
|
3630
3637
|
})
|
|
3631
3638
|
: null;
|
|
3632
|
-
const
|
|
3639
|
+
const hasInlineN3 = input && typeof input === 'object' && !Array.isArray(input) && typeof input.n3 === 'string';
|
|
3640
|
+
const parsedInput = parsedSourceList || parsedTextInput || (hasInlineN3 ? null : normalizeParsedReasonerInputSync(input));
|
|
3633
3641
|
const rdfFactory = rdfjs ? getDataFactory(dataFactory) : null;
|
|
3634
3642
|
|
|
3635
3643
|
const __oldEnforceHttps = deref.getEnforceHttpsEnabled();
|
|
@@ -3700,8 +3708,7 @@ function reasonStream(input, opts = {}) {
|
|
|
3700
3708
|
for (const qdf of queryDerived) {
|
|
3701
3709
|
const payload = { triple: useRdfCompatibility ? tripleToRdfCompatible(qdf.fact, prefixes) : tripleToN3(qdf.fact, prefixes), df: qdf };
|
|
3702
3710
|
if (rdfFactory) {
|
|
3703
|
-
|
|
3704
|
-
if (quad) payload.quad = quad;
|
|
3711
|
+
addRdfJsPayloadQuads(payload, maybeTripleToRdfJsQuads(qdf.fact, rdfFactory, skipUnsupportedRdfJs));
|
|
3705
3712
|
}
|
|
3706
3713
|
onDerived(payload);
|
|
3707
3714
|
}
|
|
@@ -3719,8 +3726,7 @@ function reasonStream(input, opts = {}) {
|
|
|
3719
3726
|
df,
|
|
3720
3727
|
};
|
|
3721
3728
|
if (rdfFactory) {
|
|
3722
|
-
|
|
3723
|
-
if (quad) payload.quad = quad;
|
|
3729
|
+
addRdfJsPayloadQuads(payload, maybeTripleToRdfJsQuads(df.fact, rdfFactory, skipUnsupportedRdfJs));
|
|
3724
3730
|
}
|
|
3725
3731
|
onDerived(payload);
|
|
3726
3732
|
}
|
|
@@ -3761,12 +3767,10 @@ function reasonStream(input, opts = {}) {
|
|
|
3761
3767
|
};
|
|
3762
3768
|
|
|
3763
3769
|
if (rdfFactory) {
|
|
3764
|
-
__out.closureQuads = closureTriples
|
|
3765
|
-
|
|
3766
|
-
|
|
3767
|
-
__out.queryQuads = queryTriples
|
|
3768
|
-
.map((t) => maybeTripleToRdfJsQuad(t, rdfFactory, skipUnsupportedRdfJs))
|
|
3769
|
-
.filter(Boolean);
|
|
3770
|
+
__out.closureQuads = closureTriples.flatMap((t) =>
|
|
3771
|
+
maybeTripleToRdfJsQuads(t, rdfFactory, skipUnsupportedRdfJs),
|
|
3772
|
+
);
|
|
3773
|
+
__out.queryQuads = queryTriples.flatMap((t) => maybeTripleToRdfJsQuads(t, rdfFactory, skipUnsupportedRdfJs));
|
|
3770
3774
|
}
|
|
3771
3775
|
deref.setEnforceHttpsEnabled(__oldEnforceHttps);
|
|
3772
3776
|
return __out;
|
|
@@ -3797,9 +3801,9 @@ function reasonRdfJs(input, opts = {}) {
|
|
|
3797
3801
|
...restOpts,
|
|
3798
3802
|
rdfjs: false,
|
|
3799
3803
|
onDerived: ({ df }) => {
|
|
3800
|
-
const
|
|
3801
|
-
if (
|
|
3802
|
-
queue.push(
|
|
3804
|
+
const quads = maybeTripleToRdfJsQuads(df.fact, rdfFactory, skipUnsupportedRdfJs);
|
|
3805
|
+
if (quads.length) {
|
|
3806
|
+
queue.push(...quads);
|
|
3803
3807
|
flush();
|
|
3804
3808
|
}
|
|
3805
3809
|
},
|
|
@@ -3828,7 +3832,15 @@ function reasonRdfJs(input, opts = {}) {
|
|
|
3828
3832
|
// Minimal export surface for Node + browser/worker
|
|
3829
3833
|
function main() {
|
|
3830
3834
|
// Lazily require to avoid hard cycles in the module graph.
|
|
3831
|
-
|
|
3835
|
+
const result = require('./cli').main();
|
|
3836
|
+
if (result && typeof result.then === 'function') {
|
|
3837
|
+
result.catch((e) => {
|
|
3838
|
+
const msg = e && e.stack ? e.stack : e && e.message ? e.message : String(e);
|
|
3839
|
+
console.error(msg);
|
|
3840
|
+
process.exit(1);
|
|
3841
|
+
});
|
|
3842
|
+
}
|
|
3843
|
+
return result;
|
|
3832
3844
|
}
|
|
3833
3845
|
|
|
3834
3846
|
// ---------------------------------------------------------------------------
|
package/lib/rdfjs.js
CHANGED
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
|
|
10
10
|
const {
|
|
11
11
|
XSD_NS,
|
|
12
|
+
LOG_NS,
|
|
12
13
|
Literal: InternalLiteral,
|
|
13
14
|
Iri,
|
|
14
15
|
Blank,
|
|
@@ -19,6 +20,7 @@ const {
|
|
|
19
20
|
Triple,
|
|
20
21
|
Rule,
|
|
21
22
|
PrefixEnv,
|
|
23
|
+
annotateQuotedGraphTerm,
|
|
22
24
|
literalParts,
|
|
23
25
|
} = require('./prelude');
|
|
24
26
|
const { termToN3, tripleToN3 } = require('./printing');
|
|
@@ -322,6 +324,49 @@ function internalRdf12TermToRdfJs(term, factory, position) {
|
|
|
322
324
|
return internalTermToRdfJs(term, rdfFactory, position);
|
|
323
325
|
}
|
|
324
326
|
|
|
327
|
+
function isDefaultGraphTerm(term) {
|
|
328
|
+
return isRdfJsTerm(term) && term.termType === 'DefaultGraph';
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
function assertDefaultGraphForRdfJsQuadTerm(term, position) {
|
|
332
|
+
if (!isDefaultGraphTerm(term.graph)) {
|
|
333
|
+
throw new TypeError(`RDF/JS Quad terms with named graphs are not supported in ${position}`);
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
function rdfJsGraphNameToInternal(term, position = 'quad.graph') {
|
|
338
|
+
assertSupportedRdfJsTerm(term, position);
|
|
339
|
+
switch (term.termType) {
|
|
340
|
+
case 'NamedNode':
|
|
341
|
+
return new Iri(term.value);
|
|
342
|
+
case 'BlankNode':
|
|
343
|
+
return new Blank(`_:${term.value}`);
|
|
344
|
+
case 'DefaultGraph':
|
|
345
|
+
return null;
|
|
346
|
+
default:
|
|
347
|
+
throw new TypeError(`Invalid RDF graph termType ${term.termType}`);
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
function internalGraphNameToRdfJs(term, factory, position = 'graph') {
|
|
352
|
+
if (term instanceof Iri || term instanceof Blank) return internalTermToRdfJs(term, factory, position);
|
|
353
|
+
return unsupportedRdfJsTerm(term, position);
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
function graphKey(term) {
|
|
357
|
+
return `${term.termType}:${term.value}`;
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
function isInternalLogNameOfTriple(triple) {
|
|
361
|
+
return (
|
|
362
|
+
triple instanceof Triple &&
|
|
363
|
+
(triple.s instanceof Iri || triple.s instanceof Blank) &&
|
|
364
|
+
triple.p instanceof Iri &&
|
|
365
|
+
triple.p.value === LOG_NS + 'nameOf' &&
|
|
366
|
+
triple.o instanceof GraphTerm
|
|
367
|
+
);
|
|
368
|
+
}
|
|
369
|
+
|
|
325
370
|
function assertRdfJsQuadShape(subject, predicate, object, graph) {
|
|
326
371
|
if (!['NamedNode', 'BlankNode', 'Quad'].includes(subject.termType)) {
|
|
327
372
|
throw new TypeError(`Invalid RDF subject termType ${subject.termType}`);
|
|
@@ -350,13 +395,22 @@ function internalTripleToRdfJsQuadInGraph(triple, graph, factory) {
|
|
|
350
395
|
function internalTripleToRdfJsQuad(triple, factory) {
|
|
351
396
|
const rdfFactory = getDataFactory(factory);
|
|
352
397
|
return rdfFactory.quad(
|
|
353
|
-
|
|
398
|
+
internalRdf12TermToRdfJs(triple.s, rdfFactory, 'subject'),
|
|
354
399
|
internalTermToRdfJs(triple.p, rdfFactory, 'predicate'),
|
|
355
|
-
|
|
400
|
+
internalRdf12TermToRdfJs(triple.o, rdfFactory, 'object'),
|
|
356
401
|
rdfFactory.defaultGraph(),
|
|
357
402
|
);
|
|
358
403
|
}
|
|
359
404
|
|
|
405
|
+
function internalTripleToRdfJsQuads(triple, factory) {
|
|
406
|
+
const rdfFactory = getDataFactory(factory);
|
|
407
|
+
if (isInternalLogNameOfTriple(triple)) {
|
|
408
|
+
const graph = internalGraphNameToRdfJs(triple.s, rdfFactory, 'graph');
|
|
409
|
+
return (triple.o.triples || []).map((inner) => internalTripleToRdfJsQuadInGraph(inner, graph, rdfFactory));
|
|
410
|
+
}
|
|
411
|
+
return [internalTripleToRdfJsQuad(triple, rdfFactory)];
|
|
412
|
+
}
|
|
413
|
+
|
|
360
414
|
function escapeStringForN3(value) {
|
|
361
415
|
return JSON.stringify(String(value));
|
|
362
416
|
}
|
|
@@ -388,7 +442,14 @@ function rdfJsTermToN3(term, position = 'term') {
|
|
|
388
442
|
return `${lexical}^^<${datatype}>`;
|
|
389
443
|
}
|
|
390
444
|
case 'Quad':
|
|
391
|
-
|
|
445
|
+
if (String(position).endsWith('.predicate') || position === 'quad.predicate' || position === 'predicate') {
|
|
446
|
+
throw new TypeError(`Quoted triple terms are not valid RDF predicates in ${position}`);
|
|
447
|
+
}
|
|
448
|
+
assertDefaultGraphForRdfJsQuadTerm(term, position);
|
|
449
|
+
return `{ ${rdfJsTermToN3(term.subject, `${position}.subject`)} ${rdfJsTermToN3(
|
|
450
|
+
term.predicate,
|
|
451
|
+
`${position}.predicate`,
|
|
452
|
+
)} ${rdfJsTermToN3(term.object, `${position}.object`)} . }`;
|
|
392
453
|
default:
|
|
393
454
|
throw new TypeError(`Unsupported RDF/JS termType ${JSON.stringify(term.termType)} in ${position}`);
|
|
394
455
|
}
|
|
@@ -408,8 +469,21 @@ function rdfJsTermToInternal(term, position = 'term') {
|
|
|
408
469
|
return new InternalLiteral(rdfJsTermToN3(term, position));
|
|
409
470
|
case 'DefaultGraph':
|
|
410
471
|
throw new TypeError(`DefaultGraph is not a valid standalone N3 term in ${position}`);
|
|
411
|
-
case 'Quad':
|
|
412
|
-
|
|
472
|
+
case 'Quad': {
|
|
473
|
+
if (String(position).endsWith('.predicate') || position === 'quad.predicate' || position === 'predicate') {
|
|
474
|
+
throw new TypeError(`Quoted triple terms are not valid RDF predicates in ${position}`);
|
|
475
|
+
}
|
|
476
|
+
assertDefaultGraphForRdfJsQuadTerm(term, position);
|
|
477
|
+
return annotateQuotedGraphTerm(
|
|
478
|
+
new GraphTerm([
|
|
479
|
+
new Triple(
|
|
480
|
+
rdfJsTermToInternal(term.subject, `${position}.subject`),
|
|
481
|
+
rdfJsTermToInternal(term.predicate, `${position}.predicate`),
|
|
482
|
+
rdfJsTermToInternal(term.object, `${position}.object`),
|
|
483
|
+
),
|
|
484
|
+
]),
|
|
485
|
+
);
|
|
486
|
+
}
|
|
413
487
|
default:
|
|
414
488
|
throw new TypeError(`Unsupported RDF/JS termType ${JSON.stringify(term.termType)} in ${position}`);
|
|
415
489
|
}
|
|
@@ -417,22 +491,58 @@ function rdfJsTermToInternal(term, position = 'term') {
|
|
|
417
491
|
|
|
418
492
|
function rdfJsQuadToInternalTriple(quad) {
|
|
419
493
|
if (!isRdfJsQuad(quad)) throw new TypeError('Expected an RDF/JS Quad');
|
|
420
|
-
|
|
421
|
-
throw new TypeError('Named graph quads are not supported by Eyeling input; use the default graph only');
|
|
422
|
-
}
|
|
423
|
-
return new Triple(
|
|
494
|
+
const inner = new Triple(
|
|
424
495
|
rdfJsTermToInternal(quad.subject, 'quad.subject'),
|
|
425
496
|
rdfJsTermToInternal(quad.predicate, 'quad.predicate'),
|
|
426
497
|
rdfJsTermToInternal(quad.object, 'quad.object'),
|
|
427
498
|
);
|
|
499
|
+
const graph = rdfJsGraphNameToInternal(quad.graph, 'quad.graph');
|
|
500
|
+
if (!graph) return inner;
|
|
501
|
+
return new Triple(graph, new Iri(LOG_NS + 'nameOf'), annotateQuotedGraphTerm(new GraphTerm([inner])));
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
function rdfJsQuadsToInternalTriples(quads) {
|
|
505
|
+
const out = [];
|
|
506
|
+
const namedGraphs = new Map();
|
|
507
|
+
|
|
508
|
+
for (const quad of quads) {
|
|
509
|
+
if (!isRdfJsQuad(quad)) throw new TypeError('Expected an RDF/JS Quad');
|
|
510
|
+
const inner = new Triple(
|
|
511
|
+
rdfJsTermToInternal(quad.subject, 'quad.subject'),
|
|
512
|
+
rdfJsTermToInternal(quad.predicate, 'quad.predicate'),
|
|
513
|
+
rdfJsTermToInternal(quad.object, 'quad.object'),
|
|
514
|
+
);
|
|
515
|
+
const graph = rdfJsGraphNameToInternal(quad.graph, 'quad.graph');
|
|
516
|
+
if (!graph) {
|
|
517
|
+
out.push(inner);
|
|
518
|
+
continue;
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
const key = graphKey(quad.graph);
|
|
522
|
+
let group = namedGraphs.get(key);
|
|
523
|
+
if (!group) {
|
|
524
|
+
group = { graph, triples: [] };
|
|
525
|
+
namedGraphs.set(key, group);
|
|
526
|
+
}
|
|
527
|
+
group.triples.push(inner);
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
for (const { graph, triples } of namedGraphs.values()) {
|
|
531
|
+
out.push(new Triple(graph, new Iri(LOG_NS + 'nameOf'), annotateQuotedGraphTerm(new GraphTerm(triples))));
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
return out;
|
|
428
535
|
}
|
|
429
536
|
|
|
430
537
|
function rdfJsQuadToN3(quad) {
|
|
431
538
|
if (!isRdfJsQuad(quad)) throw new TypeError('Expected an RDF/JS Quad');
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
539
|
+
return tripleToN3(rdfJsQuadToInternalTriple(quad), PrefixEnv.newDefault());
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
function rdfJsQuadsToN3(quads) {
|
|
543
|
+
return rdfJsQuadsToInternalTriples(quads)
|
|
544
|
+
.map((triple) => tripleToN3(triple, PrefixEnv.newDefault()))
|
|
545
|
+
.join('\n');
|
|
436
546
|
}
|
|
437
547
|
|
|
438
548
|
function collectIterableToArray(iterable, label) {
|
|
@@ -477,6 +587,11 @@ function getPrefixesText(input) {
|
|
|
477
587
|
return '';
|
|
478
588
|
}
|
|
479
589
|
|
|
590
|
+
function getN3Text(input) {
|
|
591
|
+
if (!isObject(input)) return '';
|
|
592
|
+
return typeof input.n3 === 'string' ? input.n3 : '';
|
|
593
|
+
}
|
|
594
|
+
|
|
480
595
|
function joinN3Sections(parts) {
|
|
481
596
|
return parts
|
|
482
597
|
.filter((part) => typeof part === 'string' && part.length > 0)
|
|
@@ -745,7 +860,7 @@ function appendSyncQuadFacts(doc, input) {
|
|
|
745
860
|
const quads = collectIterableToArray(quadsInfo.value, quadsInfo.label);
|
|
746
861
|
return {
|
|
747
862
|
...doc,
|
|
748
|
-
triples: doc.triples.concat(quads
|
|
863
|
+
triples: doc.triples.concat(rdfJsQuadsToInternalTriples(quads)),
|
|
749
864
|
};
|
|
750
865
|
}
|
|
751
866
|
|
|
@@ -755,7 +870,7 @@ async function appendAsyncQuadFacts(doc, input) {
|
|
|
755
870
|
const quads = await collectAsyncIterableToArray(quadsInfo.value, quadsInfo.label);
|
|
756
871
|
return {
|
|
757
872
|
...doc,
|
|
758
|
-
triples: doc.triples.concat(quads
|
|
873
|
+
triples: doc.triples.concat(rdfJsQuadsToInternalTriples(quads)),
|
|
759
874
|
};
|
|
760
875
|
}
|
|
761
876
|
|
|
@@ -774,13 +889,13 @@ async function normalizeParsedReasonerInputAsync(input) {
|
|
|
774
889
|
function normalizeReasonerInputSync(input) {
|
|
775
890
|
if (typeof input === 'string') return input;
|
|
776
891
|
const parsed = normalizeParsedReasonerInputSync(input);
|
|
777
|
-
|
|
892
|
+
const n3Text = getN3Text(input);
|
|
893
|
+
if (parsed) return joinN3Sections([n3Text, serializeEyelingDocument(parsed)]);
|
|
778
894
|
if (!isObject(input)) {
|
|
779
895
|
throw new TypeError(
|
|
780
896
|
'Reasoner input must be an N3 string, an Eyeling AST/rule object, or an object containing RDF/JS quads plus optional rules',
|
|
781
897
|
);
|
|
782
898
|
}
|
|
783
|
-
if (typeof input.n3 === 'string') return input.n3;
|
|
784
899
|
|
|
785
900
|
const quadsInfo = pickInputQuadIterable(input);
|
|
786
901
|
const rulesText = getRulesText(input);
|
|
@@ -788,25 +903,25 @@ function normalizeReasonerInputSync(input) {
|
|
|
788
903
|
const prefixesText = getPrefixesText(input);
|
|
789
904
|
|
|
790
905
|
if (!quadsInfo) {
|
|
791
|
-
if (rulesText || factsText || prefixesText) return joinN3Sections([prefixesText, factsText, rulesText]);
|
|
906
|
+
if (n3Text || rulesText || factsText || prefixesText) return joinN3Sections([prefixesText, n3Text, factsText, rulesText]);
|
|
792
907
|
throw new TypeError('Input object must provide n3 text, Eyeling AST/rule objects, or RDF/JS quads/facts/dataset');
|
|
793
908
|
}
|
|
794
909
|
|
|
795
910
|
const quads = collectIterableToArray(quadsInfo.value, quadsInfo.label);
|
|
796
|
-
const quadText = quads
|
|
797
|
-
return joinN3Sections([prefixesText, factsText, quadText, rulesText]);
|
|
911
|
+
const quadText = rdfJsQuadsToN3(quads);
|
|
912
|
+
return joinN3Sections([prefixesText, n3Text, factsText, quadText, rulesText]);
|
|
798
913
|
}
|
|
799
914
|
|
|
800
915
|
async function normalizeReasonerInputAsync(input) {
|
|
801
916
|
if (typeof input === 'string') return input;
|
|
802
917
|
const parsed = await normalizeParsedReasonerInputAsync(input);
|
|
803
|
-
|
|
918
|
+
const n3Text = getN3Text(input);
|
|
919
|
+
if (parsed) return joinN3Sections([n3Text, serializeEyelingDocument(parsed)]);
|
|
804
920
|
if (!isObject(input)) {
|
|
805
921
|
throw new TypeError(
|
|
806
922
|
'Reasoner input must be an N3 string, an Eyeling AST/rule object, or an object containing RDF/JS quads plus optional rules',
|
|
807
923
|
);
|
|
808
924
|
}
|
|
809
|
-
if (typeof input.n3 === 'string') return input.n3;
|
|
810
925
|
|
|
811
926
|
const quadsInfo = pickInputQuadIterable(input);
|
|
812
927
|
const rulesText = getRulesText(input);
|
|
@@ -814,13 +929,13 @@ async function normalizeReasonerInputAsync(input) {
|
|
|
814
929
|
const prefixesText = getPrefixesText(input);
|
|
815
930
|
|
|
816
931
|
if (!quadsInfo) {
|
|
817
|
-
if (rulesText || factsText || prefixesText) return joinN3Sections([prefixesText, factsText, rulesText]);
|
|
932
|
+
if (n3Text || rulesText || factsText || prefixesText) return joinN3Sections([prefixesText, n3Text, factsText, rulesText]);
|
|
818
933
|
throw new TypeError('Input object must provide n3 text, Eyeling AST/rule objects, or RDF/JS quads/facts/dataset');
|
|
819
934
|
}
|
|
820
935
|
|
|
821
936
|
const quads = await collectAsyncIterableToArray(quadsInfo.value, quadsInfo.label);
|
|
822
|
-
const quadText = quads
|
|
823
|
-
return joinN3Sections([prefixesText, factsText, quadText, rulesText]);
|
|
937
|
+
const quadText = rdfJsQuadsToN3(quads);
|
|
938
|
+
return joinN3Sections([prefixesText, n3Text, factsText, quadText, rulesText]);
|
|
824
939
|
}
|
|
825
940
|
|
|
826
941
|
module.exports = {
|
|
@@ -831,8 +946,10 @@ module.exports = {
|
|
|
831
946
|
rdfJsTermToN3,
|
|
832
947
|
rdfJsQuadToN3,
|
|
833
948
|
rdfJsQuadToInternalTriple,
|
|
949
|
+
rdfJsQuadsToInternalTriples,
|
|
834
950
|
internalTermToRdfJs,
|
|
835
951
|
internalTripleToRdfJsQuad,
|
|
952
|
+
internalTripleToRdfJsQuads,
|
|
836
953
|
internalTripleToRdfJsQuadInGraph,
|
|
837
954
|
normalizeParsedReasonerInputSync,
|
|
838
955
|
normalizeReasonerInputSync,
|