LINCD.js
Linked INteropeable Code & Data
All the tools you need to build Linked Data applications with ease in one package
With Linked Components you can rapidly prototype an interface powered by Linked Data.
To our knowledge, LINCD.js is the only linked data library that supports you all the way to the UI layer.
New to Linked Data? It is a W3C standard based on RDF used to build interconnected knowledge graphs. It is also known
as Structured Data which can
help search engines to present rich snippets in search results.
LINCD offers:
LINCD.js is compatible with the RDFJS data model
See also
Why?
LINCD is built from the ground up with a modern tech stack and integrates the latest developments.
This allows us to offer advanced features that go beyond other existing RDF JavaScript libraries.
Whilst also offering solutions for some major challenges in the world of Linked Data:
Making Linked Data app development easy
Graph databases are being adopted everywhere. Tons of Open Linked Data is being published.
Tools have matured, but the learning curve for developers is still steep.
LINCD significantly reduces the amount of learning required and makes it much easier to work with Linked Data.
Reusable code for Linked Data
There are tons of ontologies (reusable linked data structures) available. But without a good searchable registry, it's hard to find the right one. And starting to use a specific ontology can be time-consuming still.
Reusable UI components built specifically for Linked Data are virtually non-existent.
LINCD.org offers an open registry of quality ontologies and UI components built for those ontologies. Each of these ontology and components can be imported and used with just a few lines of code.
This library make it easy to develop and share such ontologies and components in the registry.
Solving data validation & more
Another hurdle in the adoption of Linked Data has been the openness of the RDF model.
With a lack of proper data restriction and data validation tools, maintaining a clean dataset in real life applications
has been a challenge.
W3C has since published SHACL, which is an excellent standard to tackle this. However,
the tools to work with SHACL have been minimal.
LINCD goes full in on SHACL and places SHACL's data "Shapes" right at the center of development. This creates much
simpler and cleaner code, frees developers up from thinking about which classes & properties to use and allows us to
offer advanced features like automatic data loading and data validation that to our knowledge no other Linked Data library or framework offers.
Installation
npm + node.js
npm install lincd
const lincd = require("lincd");
See this tutorial on how to build linked data applications with LINCD.js
UI Components built for Linked Data
UI components run on data. In a typical development environment, the component simply takes low level data like strings
,numbers
and booleans
as variables or 'props' (in React).
The developer is usually responsible for obtaining this data from a database, and then manually providing the right data to each prop/variable of the component.
But with Linked Data we can reuse data structures. So what if we had components that consume these reusable data structures?
All the developer has to do then, is to obtain data with the right structure, and hand it to the component.
That is exactly what we've made possible with LINCD!
Components consuming Shapes
LINCD introduces the concept of Linked Components.
These are UI components that get linked to a specific Shape.
The shape informs the structure of the data that the component expects to receive.
Here is a simple example of a functional component:
Note: Currently LINCD exclusively supports React components, though other libraries may be added in the future.
import {Person} from 'lincd-foaf/lib/shapes/Person';
export const PersonView = linkedComponent<Person>(Person, ({source}) => {
let person = source;
return <h1>Hello {person.name}!</h1>;
});
This component can then be used by providing an instance of the Person shape as it's source (using the 'of' property):
let person = new Person();
person.name = 'René';
return <PersonView of={person} />;
Linking a component (like PersonView
defined above) to a specific data structure (in this case the shape Person
) gives it several great benefits:
Automatic data loading
LINCD.js can connect to any number of triple stores and/or graph databases.
All the data you request in your component will be automatically loaded from the right place and will be available when your component runs.
In the example above, all the data is already available locally, since the person was created right there.
But consider this example:
let person = new Person('http://www.example.com/#me');
return <PersonView of={person} />;
Here we create a Person
instance for the NamedNode
with URI http://www.example.com/#me
.
The data for this node (like the name of the person) may not be loaded yet.
So LINCD will automatically query the right store for this data and only continue to render PersonView
when the data is loaded
Automatic data validation
Once you have linked your component to specific shapes (data structures), LINCD.js ensures that only those nodes in the graph that match with this shape will be allowed to be used with this component.
Because of this, you can rest assured that all the data will be there and in the right format.
That is, in the example above, PersonView
will only render once LINCD has confirmed that the provided person
instance is a valid instance of the Person
shape. With the Person
example later on this page, this would mean it has exactly one name defined under person.name
and person.knows
returns a set of valid Person
instances.
Automatic re-rendering whenever the graph changes
Linked Components automatically rerender whenever their data source updates a relevant property in the graph.
Consider this example:
let person = new Person();
person.name = 'René';
setTimeOut(() => {
person.name = 'Joe';
},1000);
return <PersonView of={person} />;
In this example, when the persons name gets updated after 1 second, PersonView
will automatically rerender to update the displayed name.
Shapes
LINCD introduces Shape classes that generate SHACL Shapes.
These classes enable automatic data validation and abstract away RDF implementation details.
Consider this example shape:
Definition
@linkedShape
export class Person extends Shape {
static targetClass: NamedNode = foaf.Person;
@literalProperty({
path: foaf.name,
required: true,
maxCount: 1,
})
get name() {
return this.getValue(foaf.name);
}
set name(val: string) {
this.overwrite(foaf.name, new Literal(val));
}
@objectProperty({
path: foaf.knows,
shape: Person,
})
get knows(): ShapeSet<Person> {
return Person.getSetOf(this.getAll(foaf.knows));
}
}
Usage
Now when we use the shape above, we can simply use plain and simple object-oriented code.
The code below creates RDF triples in the graph, but it does not need to know about any specific RDF properties or classes to use.
Instead, it simply uses the accessors from the Shape.
Furthermore, the shape class allows us to validate our graph. This happens automatically when visualising specific shapes from the graph with Linked Components
let person = new Person();
person.name = "Rene";
let person2 = new Person();
person2.name = "Jenny";
person.knows.add(person2);
console.log(Person.validate(person));
console.log(Person.validate(person2));
In-memory RDF Graph Database
With an intuitive resource-centric API:
In other RDF libraries you will have to work with raw triples / quads.
Creating triples or quads or searching your graph requires you to think in terms of subject,predicate,object,graph
.
However, a triple is simply a subject node that has points to (the predicate or 'edge') another node.
LINCD instead lets you think of your graph as nodes (subjects) that have values (the objects) for certain properties (the predicates).
In other words, you can simply update & search your graph from any node, by setting/getting properties.
Here's some examples:
Setting properties
let person = NamedNode.getOrCreate("http://ex.org/person");
let person2 = NamedNode.getOrCreate("http://ex.org/person2");
person.set(foaf.name,new Literal("John Doe"));
person2.set(foaf.name,new Literal("Jane"));
person.set(foaf.knows,person2);
This results in the following triples
<http://ex.org/person> foaf:name "John Doe"
<http://ex.org/person> foaf:knows <http://ex.org/person2>
Searching the graph
Methods like getAll(property)
and getOne(property)
and getValues(property)
all return sets of values.
These sets in turn have the same methods, to get properties of all the nodes in the set.
For example, to obtain the names of the persons that a person knows:
person.getAll(foaf.knows).getAll(foaf.name);
Alternatively you can also go straight to the literal value:
console.log(person.getAll(foaf.knows).getValues(foaf.name));
Removing properties
To remove triples from the graph, simply unset the properties
person.overwrite(foaf.knows,person3);
person.unset(foaf.knows,person3);
property.unsetAll(foaf.knows);
A registry of reusable UI components, Shapes & ontologies
lincd.org is a registry of components, shapes and ontologies built with lincd.js. Each of these can be imported and used with a few lines. This is the best place to get started to build an application powered by linked data.
Documentation
See docs.lincd.org for the full documentation plus helpful tutorials for lincd.js
Examples
See lincd.org/examples for a list of examples with source code on github.
Contributing
To make changes to lincd.js
, clone this repository and install dependencies with npm install
.
Then run npm run dev
to start the development process which watches for source file changes in src
and automatically
updates the individual transpiled files in the lib
and the bundles in the dist
folder.
Alternatively run npm run build
to build the project just once.
We welcome pull requests.
License
MPL v2