UNPKG

@netwerk-digitaal-erfgoed/ld-workbench

Version:

LDWorkbench is a Linked Data Transformation tool designed to use only SPARQL as transformation language.

104 lines 3.89 kB
import EventEmitter from 'node:events'; import sparqljs from 'sparqljs'; import getEngine from './utils/getEngine.js'; import getEngineSource from './utils/getEngineSource.js'; import { BaseQuery } from './sparql.js'; const DEFAULT_LIMIT = 10; export default class Iterator extends EventEmitter { constructor(query, endpoint, delay = 0) { super(); this.query = query; this.endpoint = endpoint; this.delay = delay; this.offset = 0; this.totalResults = 0; this.engine = getEngine(this.endpoint); } async run() { setTimeout(async () => { let resultsPerPage = 0; this.query.offset = this.offset; try { const stream = await this.engine.queryBindings(this.query.toString(), { sources: [(this.source ?? (this.source = getEngineSource(this.endpoint)))], }); stream.on('data', (binding) => { resultsPerPage++; if (!binding.has('this')) throw new Error('Missing binding $this in the Iterator result.'); const $this = binding.get('this'); if ($this.termType !== 'NamedNode') { throw new Error(`Binding $this in the Iterator result must be an Iri/NamedNode, but it is of type ${$this.termType}.`); } else { this.emit('data', $this); } }); stream.on('end', () => { this.totalResults += resultsPerPage; if (this.totalResults === 0) { this.emit('error', new IteratorError({ endpoint: this.endpoint, query: this.query, error: new Error('No results'), })); } this.offset += this.query.limit; if (resultsPerPage < this.query.limit) { this.emit('end', this.totalResults); } else { this.run(); } }); stream.on('error', e => { this.emit('error', new IteratorError({ error: e, endpoint: this.endpoint, query: this.query, })); }); } catch (e) { this.emit('error', new IteratorError({ error: e, endpoint: this.endpoint, query: this.query, })); } }, this.delay); } } export class Query extends BaseQuery { static from(query, limit) { const self = new Query(query); self.query.limit = limit ?? self.query.limit ?? DEFAULT_LIMIT; self.validate(); return self; } constructor(query) { super(query); this.query = query; } get limit() { return this.query.limit; } set offset(offset) { this.query.offset = offset; } validate() { if (!this.query.variables.find(v => v instanceof sparqljs.Wildcard || v.value === 'this')) { throw new Error('The SPARQL iterator query must select either a variable $this or a wildcard *'); } } } export class IteratorError extends Error { constructor(args) { super(`Iterator failed: ${args.error.message} for endpoint ${args.endpoint.toString()} with query:\n${args.query.toString()}`, { cause: args.error }); this.context = { endpoint: args.endpoint.toString(), query: args.query.toString(), }; } } //# sourceMappingURL=iterator.js.map