UNPKG

alcaeus-model

Version:

rdfine models for Alcaeus, Hydra client

124 lines (123 loc) 4.88 kB
import { rdf } from '@tpluscode/rdf-ns-builders'; function satisfies(criteria, value, actualCheck) { if (!criteria || !value) { return true; } return actualCheck(criteria, value); } function satisfiesMethod(criteria, operation) { return satisfies(criteria.byMethod, operation.method, (expected, actual) => { if (typeof expected === 'string') { return expected.toUpperCase() === actual.toUpperCase(); } return expected(actual); }); } function matchClass(expected, actual) { if (typeof expected === 'string') { return actual.id.value === expected; } if (typeof expected === 'function') { return expected(actual); } if ('id' in expected) { return expected.id.equals(actual.id); } return actual.id.equals(expected); } function satisfiesExpects(criteria, operation) { if (operation.expects.length === 0) { return true; } return operation.expects.some(expects => satisfies(criteria.expecting, expects, matchClass)); } function satisfiesReturns(criteria, operation) { return satisfies(criteria.returning, operation.returns, matchClass); } function satisfiesTypeOrId(criteria, operation) { const supportedOperationId = typeof criteria.bySupportedOperation === 'string' ? operation.env.namedNode(criteria.bySupportedOperation) : criteria.bySupportedOperation; return satisfies(supportedOperationId, operation, (expected, actual) => { if ('termType' in expected) { return actual.equals(expected) || actual.pointer.has(rdf.type, expected).terms.length > 0; } return expected(actual); }); } function createMatcher(operation) { return (criteria) => { if (!criteria.byMethod) { criteria.byMethod = method => method.toUpperCase() !== 'GET'; } return satisfiesReturns(criteria, operation) && satisfiesExpects(criteria, operation) && satisfiesMethod(criteria, operation) && satisfiesTypeOrId(criteria, operation); }; } const onlyExplicitNamespaces = ({ namespaces = [] }) => { const namespaceUris = namespaces.map(ns => typeof ns === 'string' ? ns : ns().value); return (quad) => namespaceUris.some(ns => quad.predicate.value.startsWith(ns)); }; const excludedProperties = ({ excludedProperties = [] }) => { const propertiesToExclude = excludedProperties.map(ex => { if (typeof ex === 'string') { return ex; } if ('id' in ex) { return ex.id.value; } return ex.value; }); return (quad) => { return !propertiesToExclude.includes(quad.predicate.value); }; }; function toResourceNodes(self, mixins) { return (nodes, quad) => { if (quad.object.termType === 'NamedNode' || quad.object.termType === 'BlankNode') { return [...nodes, self._create(self.pointer.node(quad.object), mixins)]; } return nodes; }; } export function OperationFinderMixin(Base) { return class OperationFinderClass extends Base { getOperationsDeep(stopConditions = { namespaces: [] }, previousResources = []) { const childResources = [...this.pointer.dataset.match(this.id, null, null, this._graphId)] .filter(onlyExplicitNamespaces(stopConditions)) .filter(excludedProperties(stopConditions)) .reduce(toResourceNodes(this, [OperationFinderMixin]), []); return childResources.reduce((operations, child, index, resources) => { if (previousResources.find(previous => previous.id.equals(child.id))) return operations; const currentlyVisited = [...resources, ...previousResources, this]; const childOps = child.getOperationsDeep(stopConditions, currentlyVisited); return [ ...operations, ...childOps, ]; }, this.operations || []); } findOperations(...criteria) { return this.__filterOperations(this.operations, criteria); } findOperationsDeep(stopCondition, ...moreCriteria) { return this.__filterOperations(this.getOperationsDeep(stopCondition), [stopCondition, ...moreCriteria]); } __filterOperations(operations, criteria = []) { const actualCriteria = [...criteria]; if (actualCriteria.length === 0) { actualCriteria.push({}); } return operations.reduce((operations, operation) => { if (actualCriteria.find(createMatcher(operation))) { operations.push(operation); } return operations; }, []); } }; } OperationFinderMixin.shouldApply = true;