A GraphDB and RDF4J data access library written in JavaScript to be used in Node.js.
Make sure you have Node.js version 8 or greater and Node Package Manager (npm) installed before start working with the library.
Currently the library is not published in NPM registry, but it still can be installed directly from this GitHub repository.
npm install --save Ontotext-AD/graphdb.js
- Checkout or clone the project.
- Make sure prerequisites are covered: node js and npm must be present and versions should be supported.
- Enter the project directory and execute
npm install
After any change the tests should be run and check if any existing functionality is not broken in result.
npm run test
or constantly watching for changes in source files and tests and re-execute the test suite
npm run test:watch
The best and preferred way a new feature or changes to be introduced is a test case to be written first and then the change to be implemented following the TDD approach.
The library uses Google style in conjunction with ESLint's recommended ruleset.
npm run lint
Library is managed by NPM package manager. During publishing npm consults the
.gitignore
, .npmignore
and package.json#files
property in order to decide
which resources should be published. If any change in the project structure,
.gitignore
or .npmignore
is made, then publishing must be verified in order
to be guaranteed that needed sources will be properly published.
The packaging could be verified using the npm package
command which generates
a *.tgz
archive in the project root. The archive should contain only the needed
resources.
Furture the archive could be used as a source for npm install
where the path
pointing the archive is provided.
The library is written in ES2016. During the build process source files src/
are transpiled to ES2015 and copied to lib/
directory.
A typescript definition file types.d.ts
is generated in the lib/
as well.
Documentation is generated in docs/
from the JSDoc annotations in the source
code.
npm run build
Node >= 8.16
The ServerClient
deals with operations on server level like obtaining a list
with available repositories, concrete repository or deleting repositories. In
order to work with the ServerClient
it should be configured ServerClientConfig
first.
- Configure
ServerClient
const {ServerClient, ServerClientConfig} = require('graphdbjs').server;
const {RDFMimeType} = require('graphdbjs').http;
const serverConfig = new ServerClientConfig('http://rdf4j-compliant-server/', 0, {
'Accept': RDFMimeType.SPARQL_RESULTS_JSON
});
const server = new ServerClient(serverConfig);
- Fetch repository ids
server.getRepositoryIDs().then(ids => {
// work with ids
}).catch(err => console.log(err));
- Check if repository with given name exists
server.hasRepository('repository-name').then(exists => {
if (exists) {
// repository exists -> delete it for example
}
}).catch(err => console.log(err));
- Delete repository with given name
server.deleteRepository('repository-name').then(() => {
// successfully deleted
}).catch(err => console.log(err));
- Although a repository instance can be created using a constructor which can be
seen in the examples below a client could obtain an instance of
RDFRepositoryClient
through the server client
server.getRepository('repository-name').then(repository => {
// repository is a configured RDFRepositoryClient instance
}).catch(err => console.log(err));
- Instantiating repository client
const readTimeout = 30000;
const writeTimeout = 30000;
const config = new RepositoryClientConfig(['http://GDB/repositories/my-repo'], {
'Accept': RDFMimeType.TURTLE
}, '', readTimeout, writeTimeout);
const repository = new RDFRepositoryClient(config);
- Obtaining repository client instance through a ServerClient
const ServerClient = require('server/server-client');
const ServerClientConfig = require('server/server-client-config');
const RepositoryClientConfig = require('repository/repository-client-config')
const config = new ServerClientConfig('http://GDB', 0, {});
const server = new ServerClient(config);
const readTimeout = 30000;
const writeTimeout = 30000;
const repositoryClientConfig = new RepositoryClientConfig(['http://GDB/repositories/my-repo'], {}, '', readTimeout, writeTimeout);
return server.getRepository('automotive', repositoryClientConfig).then((rdfRepositoryClient) => {
// rdfRepositoryClient is a configured instance of RDFRepositoryClient
});
Statements could be fetched using the RDFRepositoryClient.get
, RDFRepositoryClient.query
,
RDFRepositoryClient.download
.
Every reading method can get the response parsed to data objects according to RDFJS data model specification (see Response Parsers).
- Reading statements
const payload = new GetStatementsPayload()
.setResponseType(RDFMimeType.RDF_JSON)
.setSubject('<http://eunis.eea.europa.eu/countries/AZ>')
.setPredicate('<http://eunis.eea.europa.eu/rdf/schema.rdf#population>')
.setObject('"7931000"^^http://www.w3.org/2001/XMLSchema#integer')
.setContext('<http://example.org/graph3>')
.setInference(true);
return repository.get(payload).then((data) => {
// data contains requested staments in rdf json format
});
- Downloading data from repository by consuming a WritableStream
const dest = __dirname + '/statements.ttl';
const output = fs.createWriteStream(dest);
const payload = new GetStatementsPayload()
.setResponseType(RDFMimeType.TURTLE)
.get();
repository.download(payload).then((response) => {
response.on('data', (chunk) => {
output.write(new Buffer(chunk));
});
response.on('end', () => {
output.end();
});
});
-
Query evaluation against a sparql endpoint
-
SELECT query returning data objects
repository.registerParser(new SparqlXmlResultParser());
const payload = new GetQueryPayload()
.setQuery('select * where {?s ?p ?o}')
.setQueryType(QueryType.SELECT)
.setResponseType(RDFMimeType.SPARQL_RESULTS_XML)
.setLimit(100);
return repository.query(payload).then((stream) => {
stream.on('data', (bindings) => {
// the bindings stream converted to data objects with the registered parser
});
stream.on('end', () => {
// handle end of the stream
});
});
- ASK query returning a boolean result
const payload = new GetQueryPayload()
.setQuery('ask {?s ?p ?o}')
.setQueryType(QueryType.ASK)
.setResponseType(RDFMimeType.BOOLEAN_RESULT);
repository.registerParser(new SparqlJsonResultParser());
return repository.query(payload).then((data) => {
// data => true|false
});
- Uploading data in repository (POST) using ReadStream
const contentType = RDFMimeType.TURTLE;
const turtleFile = __dirname + '/statements.ttl';
fs.readFile(turtleFile, (err, stream) => {
repository.upload(stream, null, null, contentType).catch((e) => console.log(e));
});
- Overwriting data in repository (PUT) using ReadStream
const contentType = RDFMimeType.TURTLE;
const file = __dirname + '/statements-overwrite.ttl';
fs.readFile(file, (err, stream) => {
repository.overwrite(stream, null, null, contentType).catch((e) => console.log(e));
});
- Executing a sparql update query
const payload = new UpdateQueryPayload()
.setQuery('INSERT {?s ?p ?o} WHERE {?s ?p ?o}')
.setContentType(QueryContentType.X_WWW_FORM_URLENCODED)
.setInference(true)
.setTimeout(5);
return repository.update(payload).then(() => {
// repository should have been updated at this point
});
- Delete statement from given context
repository.deleteStatements(subj, pred, obj, contexts).then(() => {
});
Repository operations can be executed in transaction. In order to work with transactions
the TransactionalRepositoryClient
must be used.
TODO
TODO
Read responses of different content types might be parsed to data objects with parsers registered in the repository instance.
The library provides a way parsers to be implemented and registered with given repository instance which in turn will use them to parse the response before returning it to the client.
A parser could be implemented by extending the ContentParser
and implementing
the parse
and getSupportedType
methods.
class RdfAsJsonParser extends ContentParser {
getSupportedType() {
return 'application/rdf+json';
}
parse(content) {
// parse and return the content
return parsedContent;
}
}
The getSupportedType
method must return one of the supported RDF and SPARQL
MIME types this way defining that the parser is responsible for converting from
that type.
Parsers should be registered in the repository before executing any request.
// Import any of the predefined parsers
const {NTriplesParser} = require('graphdbjs').parser;
// And register it in the repository
repository.registerParser(new NTriplesParser());
Multiple parsers could be registered for different response types.
Registering a second parser for same content type results in overriding the previously registerted parser!
The library provides parsers for rdf formats using the N3 library:
- TurtleParser:
text/turtle
- N3parser:
text/rdf+n3
- NQuadsParser:
text/x-nquads
- NTriplesParser:
text/plain
(N-Triples
) - TrigParser:
application/x-trig
For SELECT query results in json
and xml
formats as well as boolean results
from ASK queries following parsers are wrapped and exposed:
sparqlxml-parse and
sparqljson-parse
- SparqlXmlResultParser:
application/sparql-results+xml
,text/boolean
- SparqlJsonResultParser:
application/sparql-results+json
,text/boolean