Introduce the use of EventTarget interface #3
7 changed files with 52 additions and 68 deletions
33
README.md
33
README.md
|
|
@ -18,27 +18,30 @@ Install the library into your virtual environment and project:
|
|||
npm install --save <path>
|
||||
```
|
||||
|
||||
Import and use `shacl-tulip` in your JavaScript code, for example
|
||||
Import and use `shacl-tulip` in your JavaScript code, for example:
|
||||
|
||||
```javascript
|
||||
import { ShapesDataset} from 'shacl-tulip'
|
||||
|
||||
let shapesDS = new ShapesDataset();
|
||||
const fileUrl = 'https://concepts.datalad.org/s/things/v1.shacl.ttl';
|
||||
await shapesDS.loadRDF(fileUrl);
|
||||
|
||||
console.log(shapesDS.propertyGroups)
|
||||
console.log(shapesDS.nodeShapes)
|
||||
console.log(shapesDS.nodeShapeNames)
|
||||
console.log(shapesDS.nodeShapeNamesArray)
|
||||
console.log(shapesDS.nodeShapeIRIs)
|
||||
console.log(shapesDS.prefixes)
|
||||
console.log(shapesDS.serializedGraph)
|
||||
console.log(shapesDS.graphLoaded)
|
||||
console.log(shapesDS.prefixesLoaded)
|
||||
console.log(shapesDS.graph)
|
||||
console.log(shapesDS.graph.size)
|
||||
|
||||
// Listen for and act on the 'graphLoaded' event
|
||||
shapesDS.addEventListener('graphLoaded', (event) => {
|
||||
console.log('Shapes graph fully loaded:', event.detail)
|
||||
console.log(shapesDS.propertyGroups)
|
||||
console.log(shapesDS.nodeShapes)
|
||||
console.log(shapesDS.nodeShapeNames)
|
||||
console.log(shapesDS.nodeShapeNamesArray)
|
||||
console.log(shapesDS.nodeShapeIRIs)
|
||||
console.log(shapesDS.prefixes)
|
||||
console.log(shapesDS.serializedGraph)
|
||||
console.log(shapesDS.graphLoaded)
|
||||
console.log(shapesDS.prefixesLoaded)
|
||||
console.log(shapesDS.graph)
|
||||
console.log(shapesDS.graph.size)
|
||||
});
|
||||
// Load the RDF
|
||||
shapesDS.loadRDF(fileUrl);
|
||||
```
|
||||
|
||||
[See here](src/index.js) for all `shacl-tulip` exports, and inspect the [class code](src/classes) for class-specific functionality.
|
||||
|
|
@ -16,6 +16,7 @@ export class ClassDataset extends RdfDataset {
|
|||
quad.subject.termType !== 'BlankNode' &&
|
||||
quad.object.termType !== 'BlankNode' ) {
|
||||
this.addQuad(quad)
|
||||
this.dispatchEvent(new CustomEvent('quad', { detail: quad }));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -7,11 +7,12 @@ import formatsPretty from '@rdfjs/formats/pretty.js'
|
|||
/**
|
||||
* A class wrapping an RDF dataset (quad-store) from the `rdf-ext` library.
|
||||
*/
|
||||
export class RdfDataset {
|
||||
export class RdfDataset extends EventTarget {
|
||||
/**
|
||||
* Create a wrapper object for an RDF dataset a.k.a. quad-store
|
||||
*/
|
||||
constructor() {
|
||||
super()
|
||||
this.rdfPretty = rdf.clone();
|
||||
this.rdfPretty.formats.import(formatsPretty);
|
||||
this.prefixes = {};
|
||||
|
|
@ -70,9 +71,11 @@ export class RdfDataset {
|
|||
*/
|
||||
onPrefixFn(prefix, ns) {
|
||||
this.prefixes[prefix] = ns.value;
|
||||
this.dispatchEvent(new CustomEvent('prefix', { detail: { prefix, ns } }));
|
||||
}
|
||||
onPrefixEndFn() {
|
||||
this.prefixesLoaded = true
|
||||
this.dispatchEvent(new CustomEvent('prefixesLoaded', { detail: this.prefixes }));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -81,10 +84,12 @@ export class RdfDataset {
|
|||
*/
|
||||
onDataFn(quad) {
|
||||
this.addQuad(quad)
|
||||
this.dispatchEvent(new CustomEvent('quad', { detail: quad }));
|
||||
}
|
||||
async onDataEndFn() {
|
||||
this.serializedGraph = await this.serializeGraph()
|
||||
this.graphLoaded = true
|
||||
this.dispatchEvent(new CustomEvent('graphLoaded', { detail: this.graph }));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ export class ShapesDataset extends RdfDataset {
|
|||
if (predicate === RDF.type.value && object.value === SHACL.PropertyGroup.value) {
|
||||
this.propertyGroups[subject] = {};
|
||||
}
|
||||
this.dispatchEvent(new CustomEvent('quad', { detail: quad }));
|
||||
}
|
||||
|
||||
async onDataEndFn() {
|
||||
|
|
@ -86,6 +87,7 @@ export class ShapesDataset extends RdfDataset {
|
|||
}
|
||||
this.serializedGraph = await this.serializeGraph()
|
||||
this.graphLoaded = true
|
||||
this.dispatchEvent(new CustomEvent('graphLoaded', { detail: this.graph }));
|
||||
}
|
||||
|
||||
getPropertyNodeKind(class_uri, property_uri, id_uri) {
|
||||
|
|
|
|||
|
|
@ -22,22 +22,13 @@ describe('ClassDataset', () => {
|
|||
expect(dataset.prefixesLoaded).toBe(false);
|
||||
|
||||
server = httpServer.createServer({ });
|
||||
// server.listen(8080, 'localhost');
|
||||
server.listen(PORT, HOST, (err) => {
|
||||
if (err) {
|
||||
if (err.code === 'EADDRINUSE') {
|
||||
console.warn(`Port ${PORT} is already in use. Ignoring...`);
|
||||
} else {
|
||||
throw err; // Re-throw unexpected errors
|
||||
}
|
||||
} else {
|
||||
if (err && err.code !== 'EADDRINUSE') throw err;
|
||||
console.log(`Test server started on http://${HOST}:${PORT}`);
|
||||
}
|
||||
});
|
||||
|
||||
const fileUrl = `http://${HOST}:${PORT}/tests/mockData.ttl`
|
||||
await dataset.loadRDF(fileUrl);
|
||||
await new Promise((resolve) => setTimeout(resolve, 500)); // Wait for event loop to process stream
|
||||
dataset.loadRDF(fileUrl);
|
||||
await new Promise(resolve => dataset.addEventListener('graphLoaded', resolve));
|
||||
expect(dataset.graph.size).toBe(1);
|
||||
expect(dataset.graphLoaded).toBe(true);
|
||||
expect(dataset.prefixesLoaded).toBe(true);
|
||||
|
|
|
|||
|
|
@ -8,8 +8,6 @@ let server;
|
|||
const PORT = 8080;
|
||||
const HOST = 'localhost';
|
||||
|
||||
// import httpServer from 'http-server';
|
||||
|
||||
// Test the RdfDataset class
|
||||
describe('RdfDataset', () => {
|
||||
let dataset;
|
||||
|
|
@ -83,34 +81,21 @@ describe('RdfDataset', () => {
|
|||
expect(serializedGraph).toContain('"example"');
|
||||
});
|
||||
|
||||
it('should load RDF data from a Turtle file and run associated functions', async () => {
|
||||
it('should load RDF data from a Turtle file and run associated functions and catch emits', async () => {
|
||||
console.log(`Running RdfDataset Test ${i++}...`)
|
||||
|
||||
server = httpServer.createServer({ });
|
||||
// server.listen(8080, 'localhost');
|
||||
server.listen(PORT, HOST, (err) => {
|
||||
if (err) {
|
||||
if (err.code === 'EADDRINUSE') {
|
||||
console.warn(`Port ${PORT} is already in use. Ignoring...`);
|
||||
} else {
|
||||
throw err; // Re-throw unexpected errors
|
||||
}
|
||||
} else {
|
||||
if (err && err.code !== 'EADDRINUSE') throw err;
|
||||
console.log(`Test server started on http://${HOST}:${PORT}`);
|
||||
}
|
||||
});
|
||||
|
||||
expect(dataset.graphLoaded).toBe(false);
|
||||
expect(dataset.prefixesLoaded).toBe(false);
|
||||
|
||||
const fileUrl = `http://${HOST}:${PORT}/tests/mockData.ttl`
|
||||
|
||||
const response = await fetch(fileUrl);
|
||||
expect(response.status).toBe(200);
|
||||
const text = await response.text();
|
||||
await dataset.loadRDF(fileUrl);
|
||||
// Wait for event loop to process stream
|
||||
await new Promise((resolve) => setTimeout(resolve, 500));
|
||||
const graphLoadedHandler = vi.fn();
|
||||
dataset.addEventListener('graphLoaded', graphLoadedHandler);
|
||||
dataset.loadRDF(fileUrl);
|
||||
await new Promise(resolve => dataset.addEventListener('graphLoaded', resolve));
|
||||
expect(graphLoadedHandler).toHaveBeenCalledTimes(1);
|
||||
expect(dataset.graph.size).toBe(2);
|
||||
expect(dataset.prefixes['ex']).toBe('http://example.com/');
|
||||
expect(dataset.graphLoaded).toBe(true);
|
||||
|
|
@ -121,6 +106,15 @@ describe('RdfDataset', () => {
|
|||
|
||||
});
|
||||
|
||||
it('should emit events for prefixes', async () => {
|
||||
console.log(`Running RdfDataset Test ${i++}...`)
|
||||
const prefixHandler = vi.fn();
|
||||
dataset.addEventListener('prefix', prefixHandler);
|
||||
dataset.onPrefixFn('ex', rdf.namedNode('http://example.com/'));
|
||||
expect(prefixHandler).toHaveBeenCalledTimes(1);
|
||||
expect(dataset.prefixes['ex']).toBe('http://example.com/');
|
||||
});
|
||||
|
||||
it('should resolve blank nodes correctly', () => {
|
||||
console.log(`Running RdfDataset Test ${i++}...`)
|
||||
const blankNode = rdf.blankNode();
|
||||
|
|
|
|||
|
|
@ -15,28 +15,16 @@ describe('ShapesDataset', () => {
|
|||
});
|
||||
|
||||
it('should load RDF data from Turtle file and populate all shapes-related variables', async () => {
|
||||
|
||||
expect(dataset.graphLoaded).toBe(false);
|
||||
expect(dataset.prefixesLoaded).toBe(false);
|
||||
|
||||
server = httpServer.createServer({ });
|
||||
// server.listen(8080, 'localhost');
|
||||
server.listen(PORT, HOST, (err) => {
|
||||
if (err) {
|
||||
if (err.code === 'EADDRINUSE') {
|
||||
console.warn(`Port ${PORT} is already in use. Ignoring...`);
|
||||
} else {
|
||||
throw err; // Re-throw unexpected errors
|
||||
}
|
||||
} else {
|
||||
if (err && err.code !== 'EADDRINUSE') throw err;
|
||||
console.log(`Test server started on http://${HOST}:${PORT}`);
|
||||
}
|
||||
});
|
||||
|
||||
const fileUrl = `http://${HOST}:${PORT}/tests/mockShapes.ttl`
|
||||
await dataset.loadRDF(fileUrl);
|
||||
await new Promise((resolve) => setTimeout(resolve, 500)); // Wait for event loop to process stream
|
||||
|
||||
dataset.loadRDF(fileUrl);
|
||||
await new Promise(resolve => dataset.addEventListener('graphLoaded', resolve));
|
||||
expect(dataset.graphLoaded).toBe(true);
|
||||
expect(dataset.prefixesLoaded).toBe(true);
|
||||
expect(dataset.graph.size).toBe(318); // number of quads in the mockShapes.ttl file
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue