Added generics to allow users to deviate from the standard

This commit is contained in:
Laurens Rietveld
2018-10-26 14:38:18 +02:00
parent 57be1925f0
commit baba8fe84e
6 changed files with 162 additions and 77 deletions

124
types/n3/index.d.ts vendored
View File

@@ -3,7 +3,7 @@
// Definitions by: Fred Eisele <https://github.com/phreed>
// Ruben Taelman <https://github.com/rubensworks>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
// TypeScript Version: 2.1
// TypeScript Version: 2.3
/// <reference types="node" />
@@ -78,13 +78,23 @@ export type Quad_Predicate = NamedNode | Variable;
export type Quad_Object = NamedNode | Literal | BlankNode | Variable;
export type Quad_Graph = DefaultGraph | NamedNode | BlankNode | Variable;
export class Quad implements RDF.Quad {
constructor(subject: Quad_Subject, predicate: Quad_Predicate, object: Quad_Object, graph?: Quad_Graph);
export class BaseQuad implements RDF.BaseQuad {
constructor(subject: Term, predicate: Term, object: Term, graph?: Term);
subject: Term;
predicate: Term;
object: Term;
graph: Term;
equals(other: RDF.BaseQuad): boolean;
toJSON(): string;
}
export class Quad extends BaseQuad implements RDF.Quad {
constructor(subject: Term, predicate: Term, object: Term, graph?: Term);
subject: Quad_Subject;
predicate: Quad_Predicate;
object: Quad_Object;
graph: Quad_Graph;
equals(other: RDF.Quad): boolean;
equals(other: RDF.BaseQuad): boolean;
toJSON(): string;
}
@@ -96,26 +106,28 @@ export namespace DataFactory {
function literal(value: string | number, languageOrDatatype?: string | RDF.NamedNode): Literal;
function variable(value: string): Variable;
function defaultGraph(): DefaultGraph;
function quad(subject: Quad_Subject, predicate: Quad_Predicate, object: Quad_Object, graph?: Quad_Graph): Quad;
function triple(subject: Quad_Subject, predicate: Quad_Predicate, object: Quad_Object): Quad;
function quad(subject: RDF.Quad_Subject, predicate: RDF.Quad_Predicate, object: RDF.Quad_Object, graph?: Quad_Graph): Quad;
function quad<Q_In extends RDF.BaseQuad = RDF.Quad, Q_Out extends BaseQuad = Quad>(subject: Q_In['subject'], predicate: Q_In['predicate'], object: Q_In['object'], graph?: Q_In['graph']): Q_Out;
function triple(subject: RDF.Quad_Subject, predicate: RDF.Quad_Predicate, object: RDF.Quad_Object): Quad;
function triple<Q_In extends RDF.BaseQuad = RDF.Quad, Q_Out extends BaseQuad = Quad>(subject: Q_In['subject'], predicate: Q_In['predicate'], object: Q_In['object']): Q_Out;
}
export type ErrorCallback = (err: Error, result: any) => void;
export type QuadCallback = (result: Quad) => void;
export type QuadPredicate = (result: Quad) => boolean;
export type QuadCallback<Q extends BaseQuad = Quad> = (result: Q) => void;
export type QuadPredicate<Q extends BaseQuad = Quad> = (result: Q) => boolean;
export type OTerm = RDF.Term | string | null;
export type Logger = (message?: any, ...optionalParams: any[]) => void;
export interface BlankTriple {
predicate: RDF.Quad_Predicate;
object: RDF.Quad_Object;
export interface BlankTriple<Q extends RDF.BaseQuad = RDF.Quad> {
predicate: Q['predicate'];
object: Q['object'];
}
export interface ParserConstructor {
new (options?: ParserOptions): N3Parser;
(options?: ParserOptions): N3Parser;
new<Q extends BaseQuad = Quad> (options?: ParserOptions): N3Parser<Q>;
<Q extends BaseQuad = Quad>(options?: ParserOptions): N3Parser<Q>;
}
export const Parser: ParserConstructor;
@@ -126,19 +138,19 @@ export interface ParserOptions {
baseIRI?: string;
}
export type ParseCallback = (error: Error, quad: Quad, prefixes: Prefixes) => void;
export type ParseCallback<Q extends BaseQuad = Quad> = (error: Error, quad: Q, prefixes: Prefixes) => void;
export interface N3Parser {
parse(input: string, callback: ParseCallback): void;
export interface N3Parser<Q extends BaseQuad = Quad> {
parse(input: string, callback: ParseCallback<Q>): void;
}
export interface StreamParserConstructor {
new (options?: ParserOptions): N3StreamParser;
(options?: ParserOptions): N3StreamParser;
new<Q extends BaseQuad = Quad> (options?: ParserOptions): N3StreamParser<Q>;
<Q extends BaseQuad = Quad>(options?: ParserOptions): N3StreamParser<Q>;
}
export const StreamParser: StreamParserConstructor;
export interface N3StreamParser extends RDF.Stream, NodeJS.WritableStream, RDF.Sink {
export interface N3StreamParser<Q extends BaseQuad = Quad> extends RDF.Stream<Q>, NodeJS.WritableStream, RDF.Sink<Q> {
// Below are the NodeJS.ReadableStream methods,
// we can not extend the interface directly,
// as `read` clashes with RDF.Sink.
@@ -148,10 +160,10 @@ export interface N3StreamParser extends RDF.Stream, NodeJS.WritableStream, RDF.S
pause(): this;
resume(): this;
isPaused(): boolean;
pipe<T extends NodeJS.WritableStream | RDF.Stream>(destination: T, options?: { end?: boolean; }): T;
unpipe(destination?: NodeJS.WritableStream | RDF.Stream): void;
pipe<T extends NodeJS.WritableStream | RDF.Stream<Q>>(destination: T, options?: { end?: boolean; }): T;
unpipe(destination?: NodeJS.WritableStream | RDF.Stream<Q>): void;
unshift(chunk: string | Buffer): void;
wrap(oldStream: NodeJS.ReadableStream | RDF.Stream): NodeJS.ReadableStream;
wrap(oldStream: NodeJS.ReadableStream | RDF.Stream<Q>): NodeJS.ReadableStream;
}
export interface WriterOptions {
@@ -161,66 +173,66 @@ export interface WriterOptions {
}
export interface WriterConstructor {
new (options?: WriterOptions): N3Writer;
new (fd: any, options?: WriterOptions): N3Writer;
(options?: WriterOptions): N3Writer;
(fd: any, options?: WriterOptions): N3Writer;
new<Q extends RDF.BaseQuad = RDF.Quad> (options?: WriterOptions): N3Writer<Q>;
new<Q extends RDF.BaseQuad = RDF.Quad> (fd: any, options?: WriterOptions): N3Writer<Q>;
<Q extends RDF.BaseQuad = RDF.Quad>(options?: WriterOptions): N3Writer<Q>;
<Q extends RDF.BaseQuad = RDF.Quad>(fd: any, options?: WriterOptions): N3Writer<Q>;
}
export const Writer: WriterConstructor;
export interface N3Writer {
quadToString(subject: RDF.Quad_Subject, predicate: RDF.Quad_Predicate, object: RDF.Quad_Object, graph?: RDF.Quad_Graph): string;
export interface N3Writer<Q extends RDF.BaseQuad = RDF.Quad> {
quadToString(subject: Q['subject'], predicate: Q['predicate'], object: Q['object'], graph?: Q['graph']): string;
quadsToString(quads: RDF.Quad[]): string;
addQuad(subject: RDF.Quad_Subject, predicate: RDF.Quad_Predicate, object: RDF.Quad_Object | RDF.Quad_Object[], graph?: RDF.Quad_Graph, done?: () => void): void;
addQuad(subject: Q['subject'], predicate: Q['predicate'], object: Q['object'] | Array<Q['object']>, graph?: Q['graph'], done?: () => void): void;
addQuad(quad: RDF.Quad): void;
addQuads(quads: RDF.Quad[]): void;
addPrefix(prefix: string, iri: string, done?: () => void): void;
addPrefixes(prefixes: Prefixes, done?: () => void): void;
end(err?: ErrorCallback, result?: string): void;
blank(predicate: RDF.Quad_Predicate, object: RDF.Quad_Object): BlankNode;
blank(predicate: Q['predicate'], object: Q['object']): BlankNode;
blank(triple: BlankTriple | RDF.Quad | BlankTriple[] | RDF.Quad[]): BlankNode;
list(triple: RDF.Quad_Object[]): Quad_Object[];
list(triple: Array<Q['object']>): Quad_Object[];
}
export interface StreamWriterConstructor {
new (options?: WriterOptions): N3StreamWriter;
new (fd: any, options?: WriterOptions): N3StreamWriter;
(options?: WriterOptions): N3StreamWriter;
(fd: any, options?: WriterOptions): N3StreamWriter;
new<Q extends RDF.BaseQuad = RDF.Quad> (options?: WriterOptions): N3StreamWriter<Q>;
new<Q extends RDF.BaseQuad = RDF.Quad> (fd: any, options?: WriterOptions): N3StreamWriter<Q>;
<Q extends RDF.BaseQuad = RDF.Quad>(options?: WriterOptions): N3StreamWriter<Q>;
<Q extends RDF.BaseQuad = RDF.Quad>(fd: any, options?: WriterOptions): N3StreamWriter<Q>;
}
export const StreamWriter: StreamWriterConstructor;
export interface N3StreamWriter extends NodeJS.ReadWriteStream, RDF.Source {}
export interface N3StreamWriter<Q extends RDF.BaseQuad = Quad> extends NodeJS.ReadWriteStream, RDF.Source {}
export interface N3Store extends RDF.Sink {
export interface N3Store<Q_RDF extends RDF.BaseQuad = RDF.Quad, Q_N3 extends BaseQuad = Quad> extends RDF.Sink {
readonly size: number;
addQuad(subject: RDF.Quad_Subject, predicate: RDF.Quad_Predicate, object: RDF.Quad_Object | RDF.Quad_Object[], graph?: RDF.Quad_Graph, done?: () => void): void;
addQuad(quad: RDF.Quad): void;
addQuads(quads: RDF.Quad[]): void;
removeQuad(subject: RDF.Quad_Subject, predicate: RDF.Quad_Predicate, object: RDF.Quad_Object | RDF.Quad_Object[], graph?: RDF.Quad_Graph, done?: () => void): void;
removeQuad(quad: RDF.Quad): void;
removeQuads(quads: RDF.Quad[]): void;
addQuad(subject: Q_RDF['subject'], predicate: Q_RDF['predicate'], object: Q_RDF['object'] | Array<Q_RDF['object']>, graph?: Q_RDF['graph'], done?: () => void): void;
addQuad(quad: Q_RDF): void;
addQuads(quads: Q_RDF[]): void;
removeQuad(subject: Q_RDF['subject'], predicate: Q_RDF['predicate'], object: Q_RDF['object'] | Array<Q_RDF['object']>, graph?: Q_RDF['graph'], done?: () => void): void;
removeQuad(quad: Q_RDF): void;
removeQuads(quads: Q_RDF[]): void;
getQuads(subject: OTerm, predicate: OTerm, object: OTerm | OTerm[], graph: OTerm): Quad[];
countQuads(subject: OTerm, predicate: OTerm, object: OTerm, graph: OTerm): number;
forEach(callback: QuadCallback, subject: OTerm, predicate: OTerm, object: OTerm, graph: OTerm): void;
every(callback: QuadPredicate, subject: OTerm, predicate: OTerm, object: OTerm, graph: OTerm): boolean;
some(callback: QuadPredicate, subject: OTerm, predicate: OTerm, object: OTerm, graph: OTerm): boolean;
getSubjects(predicate: OTerm, object: OTerm, graph: OTerm): Quad_Subject[];
forSubjects(callback: QuadCallback, predicate: OTerm, object: OTerm, graph: OTerm): void;
getPredicates(subject: OTerm, object: OTerm, graph: OTerm): Quad_Predicate[];
forPredicates(callback: QuadCallback, subject: OTerm, object: OTerm, graph: OTerm): void;
getObjects(subject: OTerm, predicate: OTerm, graph: OTerm): Quad_Object[];
forObjects(callback: QuadCallback, subject: OTerm, predicate: OTerm, graph: OTerm): void;
getGraphs(subject: OTerm, predicate: OTerm, object: OTerm): Quad_Graph[];
forGraphs(callback: QuadCallback, subject: OTerm, predicate: OTerm, object: OTerm): void;
forEach(callback: QuadCallback<Q_N3>, subject: OTerm, predicate: OTerm, object: OTerm, graph: OTerm): void;
every(callback: QuadPredicate<Q_N3>, subject: OTerm, predicate: OTerm, object: OTerm, graph: OTerm): boolean;
some(callback: QuadPredicate<Q_N3>, subject: OTerm, predicate: OTerm, object: OTerm, graph: OTerm): boolean;
getSubjects(predicate: OTerm, object: OTerm, graph: OTerm): Array<Q_N3['subject']>;
forSubjects(callback: QuadCallback<Q_N3>, predicate: OTerm, object: OTerm, graph: OTerm): void;
getPredicates(subject: OTerm, object: OTerm, graph: OTerm): Array<Q_N3['predicate']>;
forPredicates(callback: QuadCallback<Q_N3>, subject: OTerm, object: OTerm, graph: OTerm): void;
getObjects(subject: OTerm, predicate: OTerm, graph: OTerm): Array<Q_N3['object']>;
forObjects(callback: QuadCallback<Q_N3>, subject: OTerm, predicate: OTerm, graph: OTerm): void;
getGraphs(subject: OTerm, predicate: OTerm, object: OTerm): Array<Q_N3['graph']>;
forGraphs(callback: QuadCallback<Q_N3>, subject: OTerm, predicate: OTerm, object: OTerm): void;
createBlankNode(suggestedName?: string): BlankNode;
// match, removeMatches and deleteGraph are missing for full RDF.Store adherence
remove(stream: stream.Stream): EventEmitter;
}
export interface StoreConstructor {
new (triples?: Quad[], options?: StoreOptions): N3Store;
(triples?: Quad[], options?: StoreOptions): N3Store;
new<Q_RDF extends RDF.BaseQuad = RDF.Quad, Q_N3 extends BaseQuad = Quad> (triples?: Q_RDF[], options?: StoreOptions): N3Store<Q_RDF, Q_N3>;
<Q_RDF extends RDF.BaseQuad = RDF.Quad, Q_N3 extends BaseQuad = Quad>(triples?: Q_RDF[], options?: StoreOptions): N3Store<Q_RDF, Q_N3>;
}
export const Store: StoreConstructor;

View File

@@ -76,7 +76,13 @@ function test_doc_rdf_to_triples_2() {
}
function test_doc_rdf_stream_to_triples_1() {
const parser: N3.N3Parser = new N3.Parser({factory: N3.DataFactory});
interface QuadBnode extends N3.BaseQuad {
subject: N3.BlankNode;
predicate: N3.BlankNode;
object: N3.BlankNode;
graph: N3.BlankNode;
}
const parser: N3.N3Parser<QuadBnode> = new N3.Parser<QuadBnode>({factory: N3.DataFactory});
parser.parse('abc', console.log);
const streamParser: N3.N3StreamParser = N3.StreamParser();
@@ -177,7 +183,26 @@ function test_doc_storing() {
const bnode2: RDF.BlankNode = store.createBlankNode('abc');
const mickey: RDF.Quad = store.getQuads(N3.DataFactory.namedNode('http://ex.org/Mickey'), null, null, null)[0];
if (mickey.object.termType === "Literal") {
console.log(mickey.object.datatype);
}
console.log(mickey.subject, mickey.predicate, mickey.object, '.');
interface N3QuadGeneralized extends N3.BaseQuad {
subject: N3.Quad_Subject | N3.BlankNode | N3.Literal;
predicate: N3.Quad_Predicate | N3.BlankNode | N3.Literal;
object: N3.Quad_Object | N3.BlankNode | N3.Literal;
graph: N3.Quad_Graph | N3.BlankNode | N3.Literal;
}
interface RDFQuadGeneralized extends RDF.BaseQuad {
subject: RDF.Quad_Subject | RDF.BlankNode | RDF.Literal;
predicate: RDF.Quad_Predicate | RDF.BlankNode | RDF.Literal;
object: RDF.Quad_Object | RDF.BlankNode | RDF.Literal;
graph: RDF.Quad_Graph | RDF.BlankNode | RDF.Literal;
}
const storeGeneralized = new N3.Store<RDFQuadGeneralized, N3QuadGeneralized>();
// storeGeneralized.
storeGeneralized.addQuad(N3.DataFactory.namedNode('http://ex.org/Pluto'), N3.DataFactory.blankNode(), N3.DataFactory.namedNode('http://ex.org/Dog'));
}
function test_doc_utility() {

View File

@@ -1,3 +1,6 @@
{
"extends": "dtslint/dt.json"
"extends": "dtslint/dt.json",
"rules": {
"no-unnecessary-generics": false
}
}

View File

@@ -2,6 +2,7 @@
// Project: https://github.com/rdfjs/representation-task-force
// Definitions by: Ruben Taelman <https://github.com/rubensworks>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
// TypeScript Version: 2.3
/// <reference types="node" />
@@ -169,10 +170,42 @@ export type Quad_Object = NamedNode | Literal | BlankNode | Variable;
*/
export type Quad_Graph = DefaultGraph | NamedNode | BlankNode | Variable;
/**
* An RDF quad, taking any Term in its positions, containing the subject, predicate, object and graph terms.
*/
export interface BaseQuad {
/**
* The subject.
* @see Quad_Subject
*/
subject: Term;
/**
* The predicate.
* @see Quad_Predicate
*/
predicate: Term;
/**
* The object.
* @see Quad_Object
*/
object: Term;
/**
* The named graph.
* @see Quad_Graph
*/
graph: Term;
/**
* @param other The term to compare with.
* @return True if and only if the argument is a) of the same type b) has all components equal.
*/
equals(other: BaseQuad): boolean;
}
/**
* An RDF quad, containing the subject, predicate, object and graph terms.
*/
export interface Quad {
export interface Quad extends BaseQuad {
/**
* The subject.
* @see Quad_Subject
@@ -198,7 +231,7 @@ export interface Quad {
* @param other The term to compare with.
* @return True if and only if the argument is a) of the same type b) has all components equal.
*/
equals(other: Quad): boolean;
equals(other: BaseQuad): boolean;
}
/**
@@ -263,7 +296,7 @@ export interface DataFactory {
* @see Triple
* @see DefaultGraph
*/
triple(subject: Quad_Subject, predicate: Quad_Predicate, object: Quad_Object): Quad;
triple<Q_In extends BaseQuad = Quad, Q_Out extends BaseQuad = Quad>(subject: Q_In['subject'], predicate: Q_In['predicate'], object: Q_In['object']): Q_Out;
/**
* @param subject The quad subject term.
@@ -273,7 +306,7 @@ export interface DataFactory {
* @return A new instance of Quad.
* @see Quad
*/
quad(subject: Quad_Subject, predicate: Quad_Predicate, object: Quad_Object, graph?: Quad_Graph): Quad;
quad<Q_In extends BaseQuad = Quad, Q_Out extends BaseQuad = Quad>(subject: Q_In['subject'], predicate: Q_In['predicate'], object: Q_In['object'], graph?: Q_In['graph']): Q_Out;
}
/* Stream Interfaces */
@@ -292,14 +325,14 @@ export interface DataFactory {
* Optional events:
* * prefix(prefix: string, iri: RDF.NamedNode): This event is emitted every time a prefix is mapped to some IRI.
*/
export interface Stream extends EventEmitter {
export interface Stream<Q extends BaseQuad = Quad> extends EventEmitter {
/**
* This method pulls a quad out of the internal buffer and returns it.
* If there is no quad available, then it will return null.
*
* @return A quad from the internal buffer, or null if none is available.
*/
read(): Quad;
read(): Q;
}
/**
@@ -309,7 +342,7 @@ export interface Stream extends EventEmitter {
*
* For example, parsers and transformations which generate quads can implement the Source interface.
*/
export interface Source {
export interface Source<Q extends BaseQuad = Quad> {
/**
* Returns a stream that processes all quads matching the pattern.
*
@@ -319,8 +352,7 @@ export interface Source {
* @param graph The optional exact graph or graph regex to match.
* @return The resulting quad stream.
*/
match(subject?: Term | RegExp, predicate?: Term | RegExp, object?: Term | RegExp, graph?: Term | RegExp)
: Stream;
match(subject?: Term | RegExp, predicate?: Term | RegExp, object?: Term | RegExp, graph?: Term | RegExp): Stream<Q>;
}
/**
@@ -330,7 +362,7 @@ export interface Source {
*
* For example parsers, serializers, transformations and stores can implement the Sink interface.
*/
export interface Sink {
export interface Sink<Q extends BaseQuad = Quad> {
/**
* Consumes the given stream.
*
@@ -341,7 +373,7 @@ export interface Sink {
* @param stream The stream that will be consumed.
* @return The resulting event emitter.
*/
import(stream: Stream): EventEmitter;
import(stream: Stream<Q>): EventEmitter;
}
/**
@@ -352,7 +384,7 @@ export interface Sink {
*
* Access to stores LDP or SPARQL endpoints can be implemented with a Store inteface.
*/
export interface Store extends Source, Sink {
export interface Store<Q extends BaseQuad = Quad> extends Source, Sink {
/**
* Removes all streamed quads.
*
@@ -362,7 +394,7 @@ export interface Store extends Source, Sink {
* @param stream The stream that will be consumed.
* @return The resulting event emitter.
*/
remove(stream: Stream): EventEmitter;
remove(stream: Stream<Q>): EventEmitter;
/**
* All quads matching the pattern will be removed.
@@ -388,5 +420,5 @@ export interface Store extends Source, Sink {
* @param graph The graph term or string to match.
* @return The resulting event emitter.
*/
deleteGraph(graph: Term | string): EventEmitter;
deleteGraph(graph: Q['graph'] | string): EventEmitter;
}

View File

@@ -1,5 +1,5 @@
import { BlankNode, DataFactory, DefaultGraph, Literal, NamedNode, Quad, Sink, Source, Store, Stream, Triple, Term,
Variable } from "rdf-js";
import { BlankNode, DataFactory, DefaultGraph, Literal, NamedNode, Quad, BaseQuad, Sink, Source, Store, Stream, Triple, Term,
Variable, Quad_Graph } from "rdf-js";
import { EventEmitter } from "events";
function test_terms() {
@@ -71,7 +71,14 @@ function test_datafactory() {
const term: NamedNode = <any> {};
const triple: Quad = dataFactory.triple(term, term, term);
const quad: Quad = dataFactory.quad(term, term, term, term);
interface QuadBnode extends BaseQuad {
subject: Term;
predicate: Term;
object: Term;
graph: Term;
}
const quad = dataFactory.quad<QuadBnode, QuadBnode>(literal1, blankNode1, term, term);
const hasBnode = quad.predicate.termType === "BlankNode";
}
function test_stream() {
@@ -91,6 +98,7 @@ function test_stream() {
const matchStream9: Stream = source.match(term, term, term, /.*/);
const sink: Sink = <any> {};
const graph: Quad_Graph = <any> {};
const eventEmitter1: EventEmitter = sink.import(stream);
const store: Store = <any> {};
@@ -106,6 +114,6 @@ function test_stream() {
const eventEmitter9: EventEmitter = store.removeMatches(term, term, /.*/);
const eventEmitter10: EventEmitter = store.removeMatches(term, term, term, term);
const eventEmitter11: EventEmitter = store.removeMatches(term, term, term, /.*/);
const eventEmitter12: EventEmitter = store.deleteGraph(term);
const eventEmitter12: EventEmitter = store.deleteGraph(graph);
const eventEmitter13: EventEmitter = store.deleteGraph('http://example.org');
}

View File

@@ -1 +1,6 @@
{ "extends": "dtslint/dt.json" }
{
"extends": "dtslint/dt.json",
"rules": {
"no-unnecessary-generics": false
}
}