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

@entryscape/skos-tools

v1.1.0

Published

A library for working with SKOS and importing / updating a terminology in an EntryStore instance.

Downloads

2

Readme

skos-tools - SKOS Model and utility methods for importing SKOS into EntryStore

A library for working with SKOS and importing / updating a terminology in an EntryStore instance.

Installing

npm install @entryscape/skos-tools

Or:

yarn add @entryscape/skos-tools

You can import the library either as ES6 Modules (import) or via CommonJS (require), i.e.:

import { Concept, ConceptScheme } from '@entryscape/skos-tools';

Or:

const { Concept, ConceptScheme } = require('@entryscape/skos-tools');

In the example below we will use the CommonJS style (require).

Usage

The library have four basic capabilities:

  1. Model - interfaces for working with Concepts in ConceptSchemes without having to touch RDF.
  2. Extract - extract concepts and conceptSchemes from RDF and add them to a model.
  3. Store - creating, clearing and updating a SKOS model in an EntryStore instance.

SKOS model

The model provides an interface for working with SKOS independent of the RDF expression. There are two main classes, ConceptScheme and Concept. The methods correspond closely to the properties available on these classes in the SKOS vocabulary. For instance there are methods called broader, narrower, prefLabel, definition, relation, exactMatch to mention a few.

Each concept, as well as the concept scheme instance has its own RDF graph. This is useful when there is a need to store the graphs separately, see section on persisting the model into EntryStore.

Example of how to create a model

The following code shows how to create a concept scheme with two concepts programmatically.

const { ConceptScheme } = require('@entryscape/skos-tools');
const cs = new ConceptScheme("http://example.com", undefined, "en");
cs.title("Example terminology");
const c1 = cs.createConcept("http://example.com/c1");
cs.prefLabel("Concept 1");
const c2 = cs.createConcept("http://example.com/c2");
c2.prefLabel("Concept 2");
c2.prefLabel("Begrepp 2", "sv");
c2.broader(c1.getURI());
cs.ensureTopLevelConceptsExpressed();

Note that we set the default language in the constructor of the Concept Scheme and that is inherited in title and prefLabel (unless it is explicitly overridden like for the swedish prefLabel of concept 2).

The method call ensureTopLevelConceptsExpressed is to provide the skos:hasTopConcept relation is expressed only to the concepts that have no broader concept.

Extracting - how to extract a terminology from a single RDF file

The extract mechanism divides a larger graph into smaller graph chunks and provides and imports them into the model.

const { Graph } = require('@entryscape/rdfjson');
const { extractFromGraph } = require('@entryscape/skos-tools');
const graph = ... // Load or create a graph somehow
const cs = fromGraph(graph);

Preparing for communicating with an EntryStore instance

Any communication with an EntryStore instance requires creating a EntryStore instance for the API endpoint and authenticating. A technicality is that node.js does not allow us to use await in the global scope. To solve this we use a trick and wrap the code in an async function that we execute immediately.

const { EntryStore } = require('@entryscape/entrystore-js');
(async () => {
  const es = new EntryStore("https://some.entrystoreinstance.com");
  await es.getAuth().login("testuser", "testtest");
  // Insert your code here
})();

Creating a context as a container for a terminology

Before you can import a terminology you need to have a container for it, in EntryStore this is called a context. You can create a terminology context via EntryScape and then clear it, like this:

const { removeInStore } = require('@entryscape/skos-tools');

// Code below inside an async and authenticated function with entrystore available
const contextId = '19'; // Assuming you created context 19 in EntryScape.
const context = entrystore.getContextById(contextId);
await removeInStore(context);

Or you can create it programmatically:

const { createTermsContext } = require('@entryscape/skos-tools');

// Code below inside an async and authenticated function with entrystore available
const context = await createTermsContext(entrystore);

The context will be created in parallel with a group for managing who has access to work with entries within the context. You can mark the context to be an enhanced terminology context by providing true as the second parameter as well as provide a title for the context and the group via the third parameter. Finally, you can also define a unique name to be used for both the context and it's associated group:

const context = await createTermsContext(entrystore, true, 'Name of xyz', 'xyz');

In the examples below we will assume that a suitable context have already been created.

Creating a terminology into an EntryStore instance

In the code below we assume we have a model (conceptScheme) for the Concept Scheme already and that we have an EntryStore instance which is already authenticated.

First we need to require some methods from this library.

const { importToStore, removeInStore, consoleLogger } = require('@entryscape/skos-tools');

Second, assuming we authenticated an EntryStore instance we do the actual import from a Concept Scheme model (out of scope how we got the model in this section).

const conceptScheme = ... // A conceptScheme instance with some concepts we retrieved somehow.
const context = es.getContextById("7");
await importToStore(conceptScheme, context, false);

Note 1, we cannot have more than one Concept Scheme in the same context (a kind of container in EntryStore). Hence, we might have to clear the context first:

const conceptScheme = ... // A conceptScheme instance with some concepts we retrieved somehow.
const context = es.getContextById("7");
await removeInContext(context);
await importToStore(conceptScheme, context, false);

Note 2, a terminology can be created in an enhanced mode where every concept has two metadata graphs instead of one. In this case the EntryScape UI considers the first graph to be read-only which makes it possible to keep a distinction between imported information and manually edited information. To import information into this read-only graph we simply change the third argument to true:

await importCS(conceptScheme, context, true);

Note 3, the import step can be run in a dry run mode by setting the fourth parameter:

await importCS(conceptScheme, context, false, true);

Note 4, it is possible to get logging by providing the fifth parameter, e.g. the predefined consoleLogger:

await importCS(conceptScheme, context, false, true, consoleLogger);

Updating an existing terminology in an EntryStore instance

To update a Concept Scheme we need to use the updateInStore method.

const { updateInStore } = require('@entryscape/skos-tools');

Now we can do the update:

const conceptScheme = ... // A conceptScheme instance with some concepts we retrieved somehow.
const context = es.getContextById("7");
const report = await updateInStore(conceptScheme, context);

The updateInStore will return a report that looks like the following example:

{
  treated: 10,   // Amount of concepts in the model
  unchanged: 6,  // Amount of concepts where no change was detected
  updated: 3,    // Amount of concepts where a change where detected
  added: 1,      // Amount of new concepts that did not exist before 
  removed: 1     // Amount of concepts that was removed from the context
}

Note 1, concepts will be identified to be the same based on their URIs, hence if a concept has changed its URI the concept with the old URI will be removed and a new concept will be added. (This is one possible interpretation of the report above where a new concept was added and an old concept was removed, to figure out if that is actually what happened a deeper comparison of the URIs and metadata would be necessary.)

Note 2, it is important to know that the updateInStore looks into the concepts in the current context and detects if it was created as an enhanced terminology or not. If it was created as enhanced all changes made to the terminology using the UI will be preserved (for concepts where updated, not if they were removed altogether). If it was not created as an enhanced terminology all changes made in the UI will be overwritten.

Note 3, just like the importToStore function the updateInStore function also supports the parameter dryRun and logger.

Testing the codebase

The test can be run by executing:

yarn test

Note that one of the test suites requires that you have provided testConfig.js with information on which EntryStore instance to communicate with, see testConfig_example.js. Note that this test suite takes around 80 seconds to run due to intentional being slow. This is to make sure the EntryStore instance have time to properly index new information before verifying that imported / updated concepts are correct. In a real setting (when importing / updating) these delays can be skipped.