UNPKG

alcaeus-model

Version:

rdfine models for Alcaeus, Hydra client

115 lines (114 loc) 5.31 kB
import { hydra, rdf } from '@tpluscode/rdf-ns-builders'; import literal from 'rdf-literal'; import { createMixin } from '../Operation.js'; function only(termTypes = ['BlankNode', 'NamedNode', 'Literal']) { return function (term) { return termTypes.includes(term.term.termType); }; } function getObject(obj) { if (obj.term.termType === 'BlankNode' || obj.term.termType === 'NamedNode') { return this._create(obj, [], { parent: this, }); } return literal.fromRdf(obj.term); } export function createHydraResourceMixin(env) { function* getSupportedClasses(resource) { for (const { root: docs } of env.hydra.apiDocumentations) { if (!docs) { continue; } const classes = docs.pointer.node(resource.out(rdf.type)); for (const clas of classes.toArray()) { yield clas; } } } function HydraResourceMixin(base) { return class extends base { get operations() { const classOperations = [...getSupportedClasses(this.pointer)] .reduce((operations, clas) => [...operations, ...clas.out(hydra.supportedOperation).toArray()], []); const propertyOperations = [...this.pointer.dataset.match(null, null, this.pointer.term)] .reduce((operations, quad) => { if (quad.subject.termType !== 'NamedNode') { return operations; } return [...getSupportedClasses(this.pointer.namedNode(quad.subject))] .reduce((operations, clas) => { return [...operations, ...clas .out(hydra.supportedProperty) .has(hydra.property, quad.predicate) .out(hydra.property) .out(hydra.supportedOperation).toArray()]; }, operations); }, []); const supportedOperations = Array.prototype.concat.apply([], [...classOperations, ...propertyOperations]); const operations = supportedOperations.reduce((map, pointer) => { if (!map.has(pointer.term)) { map.set(pointer.term, this._create(pointer, [createMixin(env.hydra, this)])); } return map; }, env.termMap()); return [...operations.values()]; } get apiDocumentation() { const client = env.hydra; const id = this.pointer.out(hydra.apiDocumentation).value || client.resources.get(this.pointer)?.response.apiDocumentationLink; if (id) { const idNode = env.namedNode(id); const representation = client.apiDocumentations.find(apiDoc => apiDoc.root?.equals(idNode)); if (representation?.root) { return representation.root; } } return undefined; } getLinks(includeMissing = false) { return this.getProperties({ termTypes: ['NamedNode'] }) .filter((tuple) => tuple.supportedProperty.property?.isLink) .filter((tuple) => tuple.objects.length > 0 || includeMissing) .map((tuple) => ({ resources: tuple.objects, supportedProperty: tuple.supportedProperty, })); } getProperties(options) { const classProperties = [...getSupportedClasses(this.pointer)] .reduce((operations, clas) => [...operations, ...clas.out(hydra.supportedProperty).toArray()], []); const map = classProperties.reduce((current, supportedProperty) => { const predicate = supportedProperty.out(hydra.property).toArray()[0]; if (predicate.term.termType !== 'NamedNode' || current.has(predicate.term)) { return current; } const objects = this._getObjects(predicate.term) .toArray() .filter(only(options?.termTypes)) .map(getObject, this); return current.set(predicate.term, { objects, supportedProperty: this._create(supportedProperty), }); }, env.termMap()); return [...map.values()]; } getCollections(filter) { if (filter) { return this.collection.filter((c) => { const memberAssertions = [ ...c.memberAssertion || [], ...c.manages || [], ]; return memberAssertions.find((assertion) => assertion.matches(filter)); }); } return this.collection; } }; } HydraResourceMixin.shouldApply = true; return HydraResourceMixin; }