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

@treecg/versionawareldesinldp

v0.3.0

Published

Library for interacting with a (versioned) LDES in LDP

Downloads

71

Readme

VersionAwareLDESinLDP

npm DOI

The goal of this repository is to interact with an LDES in LDP with simple CRUD (Create, Read, Update and Read) operations.

This library has been tested with the Community Solid Server (CSS).

How does it work

The class VersionAwareLDESinLDP is an implementation of dealing with a versioned time-based LDES in LDP.

It provides functions to initialise a versioned LDES in LDP and create, read, update and delete* a member in the LDES in LDP using the version identifier. Functions:

  • create(versionID, store) appends the contents of the N3 store to the LDES in LDP.
    • also checks whether the versionID exists already. If it does, will throw an error
  • update(versionID, store) appends the contents of the N3 store to the LDES in LDP.
  • read(versionID) returns the most recent member with that version identifier.
  • delete(versionID)uses the read method as member and adds a triple that marks the resource as deleted.
  • extractVersions(VersionID) extracts the different versions using the version identifier within the LDES in LDP

*With deleting is meant that the resource is just marked as delete and not actually removed from the LDES (remember that all members of an LDES are immutable)

The class LDESinLDP is an implementation of the LDES in LDP protocol. This class is used within VersionAwareLDESinLDP and provides some utilities.

The three main features initialising, appending a member and creating a new fragment are implemented through their respective function initialise, append and newFragment. However, adding the version triple and time triple to append a member to the LDES in LDP is not done in the append function.

Using the library

Set up

First install the package

# install package
npm i @treecg/versionawareldesinldp
# (Optionally) set up a solid server
npx @solid/community-server -p 3000 -f ./data -c "@css:config/file-no-setup.json"
# or one without file system
npx @solid/community-server -c test/util/memory-no-setup.json

Initialising an LDES in LDP

const {LDPCommunication, LDESinLDP, VersionAwareLDESinLDP} = require('@treecg/versionawareldesinldp');
const ldesinldpIdentifier = 'http://localhost:3000/ldesinldp/'; // Base URL of the LDES in LDP 
const communication = new LDPCommunication();
const ldesinldp = new LDESinLDP(ldesinldpIdentifier, communication);
const versionAware = new VersionAwareLDESinLDP(ldesinldp);

// initialise
await versionAware.initialise()

From this point, this initialised LDES in LDP will be used through versionAware in the next code examples unless stated otherwise.

What is created?

- localhost:3000/
 |- ldesinldp/
  |- {timestamp}/

In the container at URL http://localhost:3000/, the ldesinldp is created. Furthermore, the ldes is described in there in that container. Which can be verified by sending a GET request

curl http://localhost:3000/ldesinldp/
@prefix dc: <http://purl.org/dc/terms/> .
@prefix dcat: <http://www.w3.org/ns/dcat#> .
@prefix ldp: <http://www.w3.org/ns/ldp#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix tree: <https://w3id.org/tree#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .


<http://localhost:3000/ldesinldp/> dc:modified "2022-09-29T13:23:30.000Z"^^xsd:dateTime ;
    rdf:type ldp:BasicContainer , ldp:Container , ldp:Resource , tree:Node ;
    ldp:contains <http://localhost:3000/ldesinldp/1664457810373/> ;
    ldp:inbox <http://localhost:3000/ldesinldp/1664457810373/> ;
    tree:relation [
        rdf:type tree:GreaterThanOrEqualToRelation ;
        tree:node <http://localhost:3000/ldesinldp/1664457810373/> ;
        tree:path dc:created ;
        tree:value "2022-09-29T13:23:30.373Z"^^xsd:dateTime
    ] .
    tree:viewDescription <http://localhost:3000/ldesinldp/#ViewDescription> .

<http://localhost:3000/ldesinldp/#EventStream> rdf:type <https://w3id.org/ldes#EventStream> ;
    ldes:timestampPath dc:created ;
    ldes:versionOfPath dc:isVersionOf ;
    tree:view <http://localhost:3000/ldesinldp/> .
    
<http://localhost:3000/ldesinldp/#ViewDescription> rdf:type tree:ViewDescription ;
    dcat:endpointURL <http://localhost:3000/ldesinldp/> ;
    dcat:servesDataset <http://localhost:3000/ldesinldp/#EventStream> ;
    ldes:managedBy <http://localhost:3000/ldesinldp/#LDESinLDPClient> .

<http://localhost:3000/ldesinldp/#LDESinLDPClient> rdf:type ldes:LDESinLDPClient ;
    ldes:bucketizeStrategy <http://localhost:3000/ldesinldp/#BucketizeStrategy> .
    
<http://localhost:3000/ldesinldp/#BucketizeStrategy> rdf:type ldes:BucketizeStrategy ;
    ldes:bucketType ldes:timestampFragmentation ;
    tree:path dc:created .

Create a version object

I want to store a resource (following triple:resourcev1 http://purl.org/dc/terms/title "Title" . ) to the LDES in LDP and want to later read it with an identifier (http://example.org/resource1).

This is done with the function create which allows to append a new version object to the LDES in LDP.

const {Store, DataFactory} = require("n3");
const namedNode = DataFactory.namedNode;
const literal = DataFactory.literal;
const store = new Store();

const memberIdentifier = '#resource'; // could also be a full IRI e.g. http://example.org/resource1v1 
const versionID = 'http://example.org/resource1';
store.addQuad(namedNode(memberIdentifier), namedNode('http://purl.org/dc/terms/title'), literal('Title'));
await versionAware.create(versionID, store, memberIdentifier);

Read a version object

I want to read the resource that has been written.

The function read extracts the latest version of the version object and returns it as an N3 Store.

const {storeToString} = require('@treecg/versionawareldesinldp'); // utility function to convert a Store to a string

const resource = await versionAware.read(versionID);
console.log(storeToString(resource))

Which outputs

<http://localhost:3000/ldesinldp/1664457810373/f982b7f3-c1e6-4a9a-8c0c-f7f40e98f638#resource> <http://purl.org/dc/terms/title> "Title" .
<http://localhost:3000/ldesinldp/1664457810373/f982b7f3-c1e6-4a9a-8c0c-f7f40e98f638#resource> <http://purl.org/dc/terms/isVersionOf> <http://example.org/resource1> .
<http://localhost:3000/ldesinldp/1664457810373/f982b7f3-c1e6-4a9a-8c0c-f7f40e98f638#resource> <http://purl.org/dc/terms/created> "2022-09-29T13:33:16.932Z"^^<http://www.w3.org/2001/XMLSchema#dateTime> .

Update a version object

I want to change the title of my resource to Fancy Title.

The function update stores a new version of this version object to the LDES in LDP.

store.addQuad(namedNode(memberIdentifier), namedNode('http://purl.org/dc/terms/title'), literal('Fancy Title'));
await versionAware.update(versionID, store, memberIdentifier);

Delete a version object

The function delete marks a members as deleted. For this, it copies the latest version object and adds a triple to indicate this deletion.

await versionAware.delete(versionID);

Reading all the version objects

The function extractVersions retrieves all members with a given version identifier.

const options = {
    amount:Infinity, // I want all members
    chronologically: true // the members are sorted from oldest to newest
} // It is also possible retrieve all members within a window by giving a `startDate` and `endDate` argument

// extractVersions extracts all members with a given version identifier constrained by the options
const resources = await versionAware.extractVersions(versionID, options)

for (const resource of resources) {
    console.log(storeToString(new Store(resource.quads)))
}

In the output, the three different version objects can clearly be seen:

  1. We created a resource with a title: "Title"
  2. Later, this resource its contents are completely rewritten with as result that it now has a title: "Fancy Title"
  3. Finally with the triple <...#resource> a ldes:DeletedLDPResource, we've marked this resource as deleted.
<http://localhost:3000/ldesinldp/1664457810373/f982b7f3-c1e6-4a9a-8c0c-f7f40e98f638#resource> <http://purl.org/dc/terms/title> "Title" .
<http://localhost:3000/ldesinldp/1664457810373/f982b7f3-c1e6-4a9a-8c0c-f7f40e98f638#resource> <http://purl.org/dc/terms/isVersionOf> <http://example.org/resource1> .
<http://localhost:3000/ldesinldp/1664457810373/f982b7f3-c1e6-4a9a-8c0c-f7f40e98f638#resource> <http://purl.org/dc/terms/created> "2022-09-29T13:33:16.932Z"^^<http://www.w3.org/2001/XMLSchema#dateTime> .

<http://localhost:3000/ldesinldp/1664457810373/5f8119f6-649c-4fea-8b4a-daf979e1a362#resource> <http://purl.org/dc/terms/title> "Fancy Title" .
<http://localhost:3000/ldesinldp/1664457810373/5f8119f6-649c-4fea-8b4a-daf979e1a362#resource> <http://purl.org/dc/terms/isVersionOf> <http://example.org/resource1> .
<http://localhost:3000/ldesinldp/1664457810373/5f8119f6-649c-4fea-8b4a-daf979e1a362#resource> <http://purl.org/dc/terms/created> "2022-09-29T14:08:58.602Z"^^<http://www.w3.org/2001/XMLSchema#dateTime> .

<http://localhost:3000/ldesinldp/1664457810373/4bc6fa4d-7b99-41aa-a289-ba3823223045#resource> <http://purl.org/dc/terms/title> "Fancy Title" .
<http://localhost:3000/ldesinldp/1664457810373/4bc6fa4d-7b99-41aa-a289-ba3823223045#resource> <http://purl.org/dc/terms/isVersionOf> <http://example.org/resource1> .
<http://localhost:3000/ldesinldp/1664457810373/4bc6fa4d-7b99-41aa-a289-ba3823223045#resource> <http://purl.org/dc/terms/created> "2022-09-29T14:08:58.690Z"^^<http://www.w3.org/2001/XMLSchema#dateTime> .
<http://localhost:3000/ldesinldp/1664457810373/4bc6fa4d-7b99-41aa-a289-ba3823223045#resource> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://w3id.org/ldes#DeletedLDPResource> .

Authenticated LDES in LDP

A private LDES in LDP can be created by using SolidCommunication and a Session (from solid-client-authn-js ).

const {SolidCommunication, LDESinLDP, VersionAwareLDESinLDP} = require('@treecg/versionawareldesinldp');
let session: Session; // Get a login session (@inrupt/solid-client-authn-node or @inrupt/solid-client-authn-browser)
const ldesinldpIdentifier = 'http://localhost:3000/ldesinldp/'; // Base URL of the LDES in LDP 
const communication = new SolidCommunication(session);
const ldesinldp = new LDESinLDP(ldesinldpIdentifier, communication);
const versionAware = new VersionAwareLDESinLDP(ldesinldp);

Getting a Session

The following code can be used to retrieve a Session if you are working with javascript node.

const {login, isLoggedin, getSession} = require('@treecg/versionawareldesinldp')

const validatedOptions = {
    applicationName: "LDES-orchestrator",
    registrationType: "dynamic",
    solidIdentityProvider: "http://localhost:3000"
};

await login(validatedOptions);
await isLoggedin(); // code that checks whether you are already logged in
const session = await getSession();

Feedback and questions

Do not hesitate to report a bug.

Further questions can also be asked to Wout Slabbinck (developer and maintainer of this repository).