n3 3.0.0-alpha.6 → 3.0.0-alpha.7
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 +2 -0
- package/browser/n3.esm.min.js +4 -4
- package/browser/n3.min.js +4 -4
- package/lib/N3Store.js +57 -2
- package/package.json +1 -1
- package/src/N3Store.js +48 -3
package/lib/N3Store.js
CHANGED
|
@@ -572,12 +572,67 @@ class N3Store {
|
|
|
572
572
|
return !this.readQuads(subjectOrQuad, predicate, object, graph).next().done;
|
|
573
573
|
}
|
|
574
574
|
|
|
575
|
-
// ### `import` adds a stream of quads to the store
|
|
575
|
+
// ### `import` adds a stream of quads to the store.
|
|
576
|
+
// It returns the stream, wrapped such that it can also be awaited
|
|
577
|
+
// as a promise of the store (per the RDF/JS `Dataset.import` signature).
|
|
576
578
|
import(stream) {
|
|
577
579
|
stream.on('data', quad => {
|
|
578
580
|
this.addQuad(quad);
|
|
579
581
|
});
|
|
580
|
-
|
|
582
|
+
|
|
583
|
+
// Only track completion once awaited, so unawaited imports keep the stream's behavior
|
|
584
|
+
const store = this;
|
|
585
|
+
let promise = null;
|
|
586
|
+
function completion() {
|
|
587
|
+
return promise || (promise = new Promise((resolve, reject) => {
|
|
588
|
+
let stopListening = null;
|
|
589
|
+
function settle(error) {
|
|
590
|
+
stopListening();
|
|
591
|
+
error ? reject(error) : resolve(store);
|
|
592
|
+
}
|
|
593
|
+
try {
|
|
594
|
+
stopListening = (0, _readableStream.finished)(stream, {
|
|
595
|
+
readable: true,
|
|
596
|
+
writable: false
|
|
597
|
+
}, settle);
|
|
598
|
+
}
|
|
599
|
+
// RDF/JS streams that are not Node.js streams only signal their end and errors
|
|
600
|
+
// and must be awaited before they finish
|
|
601
|
+
catch (_unused) {
|
|
602
|
+
stopListening = () => {
|
|
603
|
+
if (stream.removeListener) {
|
|
604
|
+
stream.removeListener('end', onFinish);
|
|
605
|
+
stream.removeListener('error', settle);
|
|
606
|
+
}
|
|
607
|
+
};
|
|
608
|
+
function onFinish() {
|
|
609
|
+
settle();
|
|
610
|
+
}
|
|
611
|
+
stream.on('end', onFinish);
|
|
612
|
+
stream.on('error', settle);
|
|
613
|
+
}
|
|
614
|
+
}));
|
|
615
|
+
}
|
|
616
|
+
const thenable = {
|
|
617
|
+
then(onFulfilled, onRejected) {
|
|
618
|
+
return completion().then(onFulfilled, onRejected);
|
|
619
|
+
},
|
|
620
|
+
catch(onRejected) {
|
|
621
|
+
return completion().catch(onRejected);
|
|
622
|
+
},
|
|
623
|
+
finally(onFinally) {
|
|
624
|
+
return completion().finally(onFinally);
|
|
625
|
+
}
|
|
626
|
+
};
|
|
627
|
+
// Return a wrapper that behaves as the stream, but is also awaitable
|
|
628
|
+
return new Proxy(stream, {
|
|
629
|
+
get(target, property) {
|
|
630
|
+
if (property === 'then' || property === 'catch' || property === 'finally') return thenable[property];
|
|
631
|
+
const value = target[property];
|
|
632
|
+
// Methods run on the stream itself, which may rely on private fields
|
|
633
|
+
return typeof value === 'function' ? value.bind(target) : value;
|
|
634
|
+
}
|
|
635
|
+
});
|
|
581
636
|
}
|
|
582
637
|
|
|
583
638
|
// ### `removeQuad` removes a quad from the store if it exists
|
package/package.json
CHANGED
package/src/N3Store.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// **N3Store** objects store N3 quads by graph in memory.
|
|
2
|
-
import { Readable } from 'readable-stream';
|
|
2
|
+
import { Readable, finished } from 'readable-stream';
|
|
3
3
|
import { default as N3DataFactory, termToId, termFromId } from './N3DataFactory';
|
|
4
4
|
import namespaces from './IRIs';
|
|
5
5
|
import { isDefaultGraph } from './N3Util';
|
|
@@ -603,10 +603,55 @@ export default class N3Store {
|
|
|
603
603
|
return !this.readQuads(subjectOrQuad, predicate, object, graph).next().done;
|
|
604
604
|
}
|
|
605
605
|
|
|
606
|
-
// ### `import` adds a stream of quads to the store
|
|
606
|
+
// ### `import` adds a stream of quads to the store.
|
|
607
|
+
// It returns the stream, wrapped such that it can also be awaited
|
|
608
|
+
// as a promise of the store (per the RDF/JS `Dataset.import` signature).
|
|
607
609
|
import(stream) {
|
|
608
610
|
stream.on('data', quad => { this.addQuad(quad); });
|
|
609
|
-
|
|
611
|
+
|
|
612
|
+
// Only track completion once awaited, so unawaited imports keep the stream's behavior
|
|
613
|
+
const store = this;
|
|
614
|
+
let promise = null;
|
|
615
|
+
function completion() {
|
|
616
|
+
return promise || (promise = new Promise((resolve, reject) => {
|
|
617
|
+
let stopListening = null;
|
|
618
|
+
function settle(error) {
|
|
619
|
+
stopListening();
|
|
620
|
+
error ? reject(error) : resolve(store);
|
|
621
|
+
}
|
|
622
|
+
try {
|
|
623
|
+
stopListening = finished(stream, { readable: true, writable: false }, settle);
|
|
624
|
+
}
|
|
625
|
+
// RDF/JS streams that are not Node.js streams only signal their end and errors
|
|
626
|
+
// and must be awaited before they finish
|
|
627
|
+
catch {
|
|
628
|
+
stopListening = () => {
|
|
629
|
+
if (stream.removeListener) {
|
|
630
|
+
stream.removeListener('end', onFinish);
|
|
631
|
+
stream.removeListener('error', settle);
|
|
632
|
+
}
|
|
633
|
+
};
|
|
634
|
+
function onFinish() { settle(); }
|
|
635
|
+
stream.on('end', onFinish);
|
|
636
|
+
stream.on('error', settle);
|
|
637
|
+
}
|
|
638
|
+
}));
|
|
639
|
+
}
|
|
640
|
+
const thenable = {
|
|
641
|
+
then(onFulfilled, onRejected) { return completion().then(onFulfilled, onRejected); },
|
|
642
|
+
catch(onRejected) { return completion().catch(onRejected); },
|
|
643
|
+
finally(onFinally) { return completion().finally(onFinally); },
|
|
644
|
+
};
|
|
645
|
+
// Return a wrapper that behaves as the stream, but is also awaitable
|
|
646
|
+
return new Proxy(stream, {
|
|
647
|
+
get(target, property) {
|
|
648
|
+
if (property === 'then' || property === 'catch' || property === 'finally')
|
|
649
|
+
return thenable[property];
|
|
650
|
+
const value = target[property];
|
|
651
|
+
// Methods run on the stream itself, which may rely on private fields
|
|
652
|
+
return typeof value === 'function' ? value.bind(target) : value;
|
|
653
|
+
},
|
|
654
|
+
});
|
|
610
655
|
}
|
|
611
656
|
|
|
612
657
|
// ### `removeQuad` removes a quad from the store if it exists
|