@tpluscode/rdfine
Version:
RDF/JS idiomatic, native, effective
62 lines (61 loc) • 2.13 kB
JavaScript
function namespacedPredicate(term, namespace) {
if (!namespace) {
throw new Error(`Cannot construct URI for property ${term}. Annotate the class with @namespace or use a NamedNode`);
}
return namespace[term];
}
function predicate(termOrString, env, namespace) {
if (typeof termOrString === 'string') {
if (termOrString.match(/^(http|urn):\/\//)) {
return env.namedNode(termOrString);
}
return namespacedPredicate(termOrString, namespace);
}
else {
return termOrString;
}
}
function sameGraph(prop) {
const edge = (subject) => subject.out(prop).toArray();
edge.predicate = prop;
edge.crossesGraphBoundaries = false;
return edge;
}
function anyGraph(prop) {
const edge = (subject, env) => {
const graphNodes = new Map();
subject.out(prop).forEach(node => {
const quadsWithSubject = subject.dataset.match(node.term);
const quadsWithObject = subject.dataset.match(null, null, node.term);
const allQuads = [...quadsWithSubject, ...quadsWithObject];
allQuads.forEach((quad) => {
if (!graphNodes.has(quad.graph.value)) {
// TODO: when clownface gets graph feature
// graphNodes.set(quad.graph.value, subject.from(quad.graph))
graphNodes.set(quad.graph.value, env.clownface({
dataset: subject.dataset,
term: quad.subject,
graph: quad.graph,
}));
}
});
});
return [...graphNodes.values()];
};
edge.predicate = prop;
edge.crossesGraphBoundaries = true;
return edge;
}
export function crossBoundaries(prop) {
return function (ns) {
return anyGraph(predicate(prop, this, ns));
};
}
export function toEdgeTraversals(namespace, env, path) {
return path.map(prop => {
if (typeof prop === 'function') {
return prop.call(env, namespace);
}
return sameGraph(predicate(prop, env, namespace));
});
}