npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

ramp-shapes

v0.11.0

Published

RAMP shapes: declarative RDF ↔ algebraic data type mapping

Downloads

12

Readme

RAMP shapes: declarative RDF ↔ algebraic data type mapping npm version

Home page | Introductory paper | Specification draft | Playground

RAMP is a type construction language, specification and an implementation of mapping operations between RDF graphs and structured data types.

Features

RAMP introduces a language based on RDF which allows to describe a runtime object interface with so-called "shapes". The shapes are basically types augumented with metadata to map them into RDF graph. Usage of such shapes allows to:

  • Map RDF graph data into JS objects.
  • Generate RDF quad/triple data from JS objects.
  • Construct SPARQL queries to fetch necessary data for given shapes.
  • (In the future) Validate that runtime object structure matches specified shape.

Feature comparison with other RDF modelling languages

| Feature | OWL/RDFS | SHACL | ShEx | JSON-LD | RAMP Shapes | |---|---|---|---|---|---| | Describes closed RDF graph structure | ❌ | ✅ | ✅ | ✅ | ✅ | | Describes data mapping / serialization | ❌ | ❌ | ❌ | requires frame definition | ✅ | | Has ability to generate query and deserialize results based on shapes | ❌ | ❌ | ❌ | ❌ | ✅ | | Has RDF representation | ✅ | ✅ | ✅ | ❌ | ✅ | | Supports RDF lists | ❌ | with workaround | ❌ | ✅ | ✅ | | Supports shape unions | ✅ | through shape targets | ✅ | ❌ | ✅ | | Supports cardinality constraints (min/max) | ✅ | ✅ | ✅ | ❌ | ✅ | | Supports recursive shapes | ✅ | depends on implementation | ✅ | ❌ | ✅ | | Supports property paths | ❌ | ✅ | ❌ | ❌ | ✅ | | Supports ignoring optional non-matching shapes | ❌ | by declaring shape severity | ❌ | ❌ | ✅ |

Installation

Install with npm install --save ramp-shapes

Usage

Try out on the interactive playground.

import * as Ramp from 'ramp-shapes';
import * as N3 from 'n3';
import * as SparqlJs from 'sparqljs';

// get graph triples (source data)
const dataset = Ramp.Rdf.dataset(new N3.Parser().parse(`
    @prefix ex: <http://example.com/schema/>.
    @prefix : <http://example.com/data/>.

    :anno1 a ex:Annotation;
        ex:start :point1;
        ex:end ("1" "2").

    :point1 a ex:Point;
        ex:position 42.
`));

// define custom shapes using Turtle syntax
const shapes = Ramp.frameShapes(Ramp.Rdf.dataset(new N3.Parser().parse(`
    @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>.
    @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>.
    @prefix xsd: <http://www.w3.org/2001/XMLSchema#>.
    @prefix ramp: <http://ramp-shapes.github.io/schema#>.
    @prefix ex: <http://example.com/schema/>.

    ex:Annotation a ramp:Record;
        ramp:typeProperty [
            ramp:name "type";
            ramp:path rdf:type;
            ramp:shape [ a ramp:Resource; ramp:termValue ex:Annotation ]
        ];
        ramp:property [
            ramp:name "id";
            ramp:path ();
            ramp:shape [ a ramp:Resource ]
        ];
        ramp:property [
            ramp:name "start";
            ramp:path ex:start;
            ramp:shape ex:Selector
        ];
        ramp:property [
            ramp:name "end";
            ramp:path ex:end;
            ramp:shape [ a ramp:Optional; ramp:item ex:Selector ]
        ].

    ex:Selector a ramp:AnyOf;
        ramp:variant ex:Point, ex:Path.

    ex:Point a ramp:Record;
        ramp:typeProperty [
            ramp:name "type";
            ramp:path rdf:type;
            ramp:shape [ a ramp:Resource; ramp:termValue ex:Point ]
        ];
        ramp:property [
            ramp:name "position";
            ramp:path ex:position;
            ramp:shape [ a ramp:Literal; ramp:termDatatype xsd:integer ]
        ].

    ex:Path a ramp:List;
        ramp:item [ a ramp:Literal; ramp:termDatatype xsd:string ].
`)));

// choose entry point shape
const shape = shapes.find(s =>
  s.id.value === 'http://example.com/schema#Annotation'
);

// use defined shapes to lower RDF graph into JS objects...
const matches = Ramp.frame({shape, dataset});
for (const match of matches) {
  /* match.value object has ex:Annotation shape, e.g.:
    {
      "type": "http://example.com/schema/Annotation",
      "id": "http://example.com/data/anno1",
      "start": {
        "type": "http://example.com/schema/Point",
        "position": 42
      },
      "end": ["1", "2"]
    }
  */

  // ... and lift JS object back into an RDF graph
  const quads = Ramp.flatten({shape, value: match.value});
  /* quads is Iterable<Rdf.Quad>, e.g.:

    :anno1 a ex:Annotation;
        ex:start _:record_044916_1.
    _:record_044916_1 a ex:Point;
        ex:position "42"^^xsd:integer.
    :anno1 ex:end _:list_044916_2.
    _:list_044916_2 rdf:first "1";
        rdf:rest _:list_044916_3.
    _:list_044916_3 rdf:first "2";
        rdf:rest rdf:nil.
  */
}

// another application of defined shapes is to generate a CONSTRUCT query
// to get necessary graph data for framing
const query = Ramp.generateQuery({
  shape,
  // (optionally) specify prefixes for SPARQL
  prefixes: {
    rdf: "http://www.w3.org/1999/02/22-rdf-syntax-ns#",
    rdfs: "http://www.w3.org/2000/01/rdf-schema#",
    xsd: "http://www.w3.org/2001/XMLSchema#",
    ex: "http://example.com/schema/",
    "": "http://example.com/data/",
  }
});
const queryString = new SparqlJs.Generator().stringify(query);
/* query is a CONSTRUCT query in SPARQL.js runtime format:

  PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
  PREFIX ex: <http://example.com/schema/>
  CONSTRUCT {
    ?record_1 rdf:type ex:Annotation.
    ?record_1 ex:start ?record_4.
    ?record_4 rdf:type ex:Point.
    ?record_4 ex:position ?literal_5.
    ?record_1 ex:start ?list_6.
    ?listNode_7 rdf:rest ?nextNode_8.
    ?listNode_7 rdf:first ?literal_9.
    ?record_1 ex:end ?record_11.
    ?record_11 rdf:type ex:Point.
    ?record_11 ex:position ?literal_12.
    ?record_1 ex:end ?list_13.
    ?listNode_14 rdf:rest ?nextNode_15.
    ?listNode_14 rdf:first ?literal_16.
  }
  WHERE {
    ?record_1 rdf:type ex:Annotation.
    {
      ?record_1 ex:start ?record_4.
      ?record_4 rdf:type ex:Point.
      ?record_4 ex:position ?literal_5.
    }
    UNION
    {
      ?record_1 ex:start ?list_6.
      ?list_6 (rdf:rest*) ?listNode_7.
      ?listNode_7 rdf:rest ?nextNode_8.
      ?listNode_7 rdf:first ?literal_9.
    }
    OPTIONAL {
      {
        ?record_1 ex:end ?record_11.
        ?record_11 rdf:type ex:Point.
        ?record_11 ex:position ?literal_12.
      }
      UNION
      {
        ?record_1 ex:end ?list_13.
        ?list_13 (rdf:rest*) ?listNode_14.
        ?listNode_14 rdf:rest ?nextNode_15.
        ?listNode_14 rdf:first ?literal_16.
      }
    }
  }
 */

References

Morozov A., Wohlgenannt G., Mouromtsev D., Pavlov D., Emelyanov Y. (2019) RAMP Shapes: Declarative RDF ↔ ADT Mapping. In: Garoufallou E., Fallucchi F., William De Luca E. (eds) Metadata and Semantic Research. MTSR 2019. Communications in Computer and Information Science, vol 1057. Springer, Cham

https://link.springer.com/chapter/10.1007/978-3-030-36599-8_4