Skip to content

Commit

Permalink
Merge pull request #406 from linkeddata/feature/extended-typing
Browse files Browse the repository at this point in the history
Improve typing of DataFactory
  • Loading branch information
megoth authored Apr 29, 2020
2 parents 1eb18e4 + 7d3ddd6 commit 5650e30
Show file tree
Hide file tree
Showing 17 changed files with 160 additions and 89 deletions.
9 changes: 9 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@
"@types/express": "^4.17.4",
"@types/jsonld": "^1.5.0",
"@types/mocha": "^7.0.2",
"@types/rdf-js": "^2.0.11",
"babel-loader": "^8.0.6",
"chai": "^4.2.0",
"diff": "^4.0.1",
Expand Down Expand Up @@ -93,7 +94,7 @@
"doc": "rm -r doc ; typedoc",
"prepublishOnly": "npm ci && npm run build && npm run build:types && npm run build:browser && npm run build:esm",
"start": "webpack-dev-server --https --port 4800",
"test": "npm run test:unit && npm run test:serialize",
"test": "npm run test:unit && npm run test:serialize && npm run test:types",
"test:clean": "rimraf tests/serialize/,*",
"test:serialize": "npm run build && npm run test:serialize:all && npm run test:clean",
"test:serialize:all": "npm run test:serialize:1 && npm run test:serialize:2 && npm run test:serialize:3 && npm run test:serialize:4 && npm run test:serialize:5 && npm run test:serialize:6 && npm run test:serialize:7 && npm run test:serialize:10 && npm run test:serialize:11 && npm run test:serialize:12 && npm run test:serialize:13",
Expand All @@ -110,6 +111,7 @@
"test:serialize:11": "cd ./tests/serialize && node ./data.js -in=structures.n3 -format=application/rdf+xml -out=,structures.xml && node diff ,structures.xml t11-ref.xml",
"test:serialize:12": "cd ./tests/serialize && node ./data.js -in=structures.n3 -format=text/turtle -out=,structures.ttl && node diff ,structures.ttl t12-ref.ttl",
"test:serialize:13": "cd ./tests/serialize && node ./data.js -in=structures.n3 -format=application/n-triples -out=,structures.nt && node ./data.js -format=application/n-triples -in=,structures.nt -format=text/turtle -out=,structures.nt.ttl && node diff ,structures.nt.ttl t13-ref.ttl",
"test:types": "tsc --noEmit --target es2019 tests/types/*.ts",
"test:unit": "mocha --growl --require ./tests/babel-register.js tests/unit/**-test.*",
"test:unit:egp": "mocha --require ./tests/babel-register.js tests/unit/fetcher-egp-test.js",
"test:unit:dev": "mocha --watch --growl --require ./tests/babel-register.js tests/unit/**-test.js"
Expand Down
1 change: 0 additions & 1 deletion src/blank-node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ export default class BlankNode extends Node implements TFBlankNode {

/**
* The identifier for the blank node
* @deprecated use [[value]] instead.
*/
public get id (): string {
return this.value
Expand Down
11 changes: 11 additions & 0 deletions src/default-graph.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import Node from './node-internal'
import { DefaultGraphTermType } from './types'
import { DefaultGraph as TFDefaultGraph } from './tf-types'
import { defaultGraphURI } from './utils/default-graph-uri'

/** The RDF default graph */
export default class DefaultGraph extends Node implements TFDefaultGraph {
value: '' = '';
termType: typeof DefaultGraphTermType = DefaultGraphTermType;
uri = defaultGraphURI

constructor () {
super('')
Expand All @@ -13,4 +16,12 @@ export default class DefaultGraph extends Node implements TFDefaultGraph {
toCanonical () {
return this.value
}

toString () {
return 'DefaultGraph';
}
}

export function isDefaultGraph(object: any): object is DefaultGraph {
return !!object && object.termType === DefaultGraphTermType;
}
34 changes: 25 additions & 9 deletions src/factories/canonical-data-factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@ import {
LiteralTermType,
NamedNodeTermType,
CollectionTermType,
GraphTermType,
} from '../types'
import { defaultGraphNode } from '../utils/default-graph-uri'
import DefaultGraph from '../default-graph'
import {
Comparable,
DataFactory,
Expand All @@ -25,15 +26,14 @@ import {
} from './factory-types'
import { isQuad, isTerm } from '../utils/terms'
import { NamedNode as TFNamedNode, Quad, Term } from '../tf-types'
import Collection from "../collection";

export { defaultGraphURI } from '../utils/default-graph-uri'

/**
* Gets the default graph
*/
export function defaultGraph(): NamedNode {
return defaultGraphNode
}
const defaultGraph = new DefaultGraph()

/** A basic internal RDFlib datafactory, which does not support Collections */
const CanonicalDataFactory: DataFactory = {
Expand All @@ -56,7 +56,7 @@ const CanonicalDataFactory: DataFactory = {
return new BlankNode(value)
},

defaultGraph,
defaultGraph: () => defaultGraph,

/**
* Compares to (rdf) objects for equality.
Expand Down Expand Up @@ -162,14 +162,29 @@ const CanonicalDataFactory: DataFactory = {
* @param object - The object
* @param graph - The containing graph
*/
quad(
quad<
S extends SubjectType = SubjectType,
P extends PredicateType = PredicateType,
O extends ObjectType = ObjectType,
G extends GraphType = GraphType
>(subject: S, predicate: P, object: O, graph?: G): Statement<S, P, O, G | DefaultGraph> {
return new Statement(subject, predicate, object, graph || defaultGraph)
},

/**
* Creates a new statement
* @param subject - The subject
* @param predicate - The predicate
* @param object - The object
* @param graph - The containing graph
*/
triple(
subject: Term | SubjectType,
predicate: Term | PredicateType,
object: Term | ObjectType,
graph?: Term | GraphType
): Statement {
graph = graph || defaultGraph()
return new Statement(subject, predicate, object, graph)
return this.quad(subject, predicate, object, graph)
},

quadToNQ(q: Statement | Quad): string {
Expand All @@ -187,10 +202,11 @@ const CanonicalDataFactory: DataFactory = {
return '<http://www.w3.org/1999/02/22-rdf-syntax-ns#nil>'
case LiteralTermType:
return Literal.toNT(term as Literal)
case GraphTermType:
case NamedNodeTermType:
return '<' + term.value + '>'
case CollectionTermType:
return '(' + term.elements.map(t => this.termToNQ(t)).join(' ') + ')'
return '(' + (term as Collection).elements.map(t => this.termToNQ(t)).join(' ') + ')'
default:
throw new Error(`Can't serialize nonstandard term type (was '${term.termType}')`)
}
Expand Down
9 changes: 9 additions & 0 deletions src/factories/factory-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import Statement from '../statement'
import NamedNode from '../named-node'
import BlankNode from '../blank-node'
import Variable from '../variable'
import DefaultGraph from '../default-graph'
import {
BlankNode as TFBlankNode,
RdfJsDataFactory,
Expand Down Expand Up @@ -64,8 +65,16 @@ export interface DataFactory<

supports: SupportTable

namedNode(value: string): NamedNode

blankNode(value?: string): BlankNode

literal(value: string, languageOrDatatype?: string | TFNamedNode): Literal

variable(value: string): Variable,

defaultGraph(): DefaultGraph,

isQuad(obj: any): obj is Statement

equals(a: Comparable, b: Comparable): boolean
Expand Down
17 changes: 0 additions & 17 deletions src/factories/rdflib-data-factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ const RDFlibDataFactory: IRDFlibDataFactory = {
* @param val The lexical value
* @param lang The language
* @param dt The datatype
* @deprecated use [[literal]] with the second and third argument combined
*/
lit (val: string, lang?: string, dt?: NamedNode): Literal {
return this.literal('' + val, lang || dt)
Expand All @@ -45,7 +44,6 @@ const RDFlibDataFactory: IRDFlibDataFactory = {
* @param predicate The predicate
* @param object The object
* @param graph The containing graph
* @deprecated use [[quad]] instead
*/
st (
subject: Quad_Subject,
Expand All @@ -55,21 +53,6 @@ const RDFlibDataFactory: IRDFlibDataFactory = {
): Statement {
return this.quad(subject, predicate, object, graph)
},

/**
* Creates a new statement
* @param subject The subject
* @param predicate The predicate
* @param object The object
* @deprecated use [[quad]] without the last argument instead
*/
triple (
subject: Quad_Subject,
predicate: Quad_Predicate,
object: Quad_Object
): Statement {
return this.quad(subject, predicate, object)
},
}

export default RDFlibDataFactory
27 changes: 14 additions & 13 deletions src/formula.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,13 +122,15 @@ export default class Formula extends Node {
* @param graph - the last part of the statement
*/
add (
subject: Quad_Subject,
predicate: Quad_Predicate,
object: Quad_Object,
subject: Quad_Subject | Quad | Quad[] | Statement | Statement[],
predicate?: Quad_Predicate,
object?: Term | string,
graph?: Quad_Graph
): number {
return this.statements
.push(this.rdfFactory.quad(subject, predicate, object, graph))
): Quad | null | this | number {
if (arguments.length === 1) {
(subject as Quad[]).forEach(st => this.add(st.subject, st.predicate, st.object, st.graph))
}
return this.statements.push(this.rdfFactory.quad(subject, predicate, object, graph))
}

/** Add a statment object
Expand All @@ -138,7 +140,10 @@ export default class Formula extends Node {
return this.statements.push(statement)
}

/** @deprecated use {this.rdfFactory.blankNode} instead */
/**
* Shortcut for adding blankNodes
* @param [id]
*/
bnode (id?: string): BlankNode {
return this.rdfFactory.blankNode(id)
}
Expand Down Expand Up @@ -763,21 +768,17 @@ export default class Formula extends Node {
* Creates a new formula with the substituting bindings applied
* @param bindings - The bindings to substitute
*/
//@ts-ignore signature not compatible with Node
substitute(bindings: Bindings): Formula {
substitute<T extends Node = Formula>(bindings: Bindings): T {
let statementsCopy = this.statements.map(function (ea) {
return (ea as Statement).substitute(bindings)
})
console.log('Formula subs statmnts:' + statementsCopy)
const y = new Formula()
y.addAll(statementsCopy as Quad[])
console.log('indexed-form subs formula:' + y)
return y
return y as unknown as T
}

/**
* @deprecated use {rdfFactory.namedNode} instead
*/
sym (uri: string, name?): NamedNode {
if (name) {
throw new Error('This feature (kb.sym with 2 args) is removed. Do not assume prefix mappings.')
Expand Down
14 changes: 7 additions & 7 deletions src/literal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import ClassOrder from './class-order'
import RDFlibNamedNode from './named-node'
import Node from './node-internal'
import {
FromValueReturns,
LiteralTermType,
ValueType
} from './types'
Expand All @@ -13,7 +14,6 @@ import { Literal as TFLiteral, Term } from './tf-types'
* An RDF literal, containing some value which isn't expressed as an IRI.
* @link https://rdf.js.org/data-model-spec/#literal-interface
*/
// @ts-ignore Incorrectly extends due to fromValue()
export default class Literal extends Node implements TFLiteral {
termType: typeof LiteralTermType = LiteralTermType

Expand Down Expand Up @@ -164,21 +164,21 @@ export default class Literal extends Node implements TFLiteral {
* Builds a literal node from an input value
* @param value - The input value
*/
static fromValue<T extends Literal>(value: ValueType): T {
static fromValue<T extends FromValueReturns>(value: ValueType): T {
if (isLiteral(value)) {
return value as T
return value as unknown as T
}
switch (typeof value) {
case 'object':
if (value instanceof Date) {
return Literal.fromDate(value) as T
return Literal.fromDate(value) as unknown as T
}
case 'boolean':
return Literal.fromBoolean(value as boolean) as T
return Literal.fromBoolean(value as boolean) as unknown as T
case 'number':
return Literal.fromNumber(value as number) as T
return Literal.fromNumber(value as number) as unknown as T
case 'string':
return new Literal(value) as T
return new Literal(value) as unknown as T
}

throw new Error("Can't make literal from " + value + ' of type ' +
Expand Down
5 changes: 1 addition & 4 deletions src/named-node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,10 +85,7 @@ export default class NamedNode extends Node implements TFNamedNode {
return this.value.split('#')[1]
}

/**
* Legacy getter and setter alias, node.uri
* @deprecated use [[value]]
*/
/** Alias for value, favored by Tim */
get uri (): string {
return this.value
}
Expand Down
6 changes: 3 additions & 3 deletions src/parse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,14 @@ type CallbackFunc = (error: any, kb: Formula | null) => void
* @param str - The input string to parse
* @param kb - The store to use
* @param base - The base URI to use
* @param contentType - The MIME content type string for the input
* @param callback - The callback to call when the data has been loaded
* @param contentType - The MIME content type string for the input - defaults to text/turtle
* @param [callback] - The callback to call when the data has been loaded
*/
export default function parse (
str: string,
kb: Formula,
base: string,
contentType: string | ContentType,
contentType: string | ContentType = 'text/turtle',
callback?: CallbackFunc
) {
contentType = contentType || TurtleContentType
Expand Down
Loading

0 comments on commit 5650e30

Please sign in to comment.