@tpluscode/rdfine
Version:
RDF/JS idiomatic, native, effective
61 lines (60 loc) • 2.21 kB
JavaScript
import * as rdfList from './rdf-list.js';
function nodeToValue(target) {
const fromTerm = (obj) => {
switch (obj.term.termType) {
case 'BlankNode':
case 'NamedNode':
if (rdfList.isList(obj)) {
return rdfList.enumerateList(target, obj, fromTerm);
}
return target._create(obj, [], { parent: target });
default:
return obj.term;
}
};
return fromTerm;
}
export function createProxy(resource) {
return new Proxy(resource, {
get(target, property) {
if (property in target || typeof property === 'symbol') {
return target[property.toString()];
}
const objects = target._getObjects(property.toString());
if (objects.values.length === 0) {
return undefined;
}
const results = objects.map(nodeToValue(target));
return results.length === 1 ? results[0] : results;
},
set(target, property, value) {
if (property in target || typeof property === 'symbol') {
target[property.toString()] = value;
return true;
}
if (typeof property === 'number') {
return false;
}
const values = Array.isArray(value) ? value : [value];
const valueNodes = values
.reduce((values, value) => {
if (typeof value === 'function') {
value = value(target.pointer);
}
if (!value || typeof value !== 'object') {
return values;
}
if (value && ('termType' in value || '_context' in value)) {
return [...values, value];
}
return [...values, value.id];
}, []);
const predicate = target.pointer.namedNode(property.toString());
target.pointer.deleteOut(predicate);
if (values.length) {
target.pointer.addOut(predicate, valueNodes);
}
return true;
},
});
}