diff --git a/.componentsignore b/.componentsignore index 723eb4fa1..a31248878 100644 --- a/.componentsignore +++ b/.componentsignore @@ -12,6 +12,7 @@ "Dict", "Error", "EventEmitter", + "FetchDocumentLoader", "GenericEventEmitter", "HashMap", "HttpErrorOptions", diff --git a/src/storage/conversion/ConversionUtil.ts b/src/storage/conversion/ConversionUtil.ts index c237061fe..b6af8a00a 100644 --- a/src/storage/conversion/ConversionUtil.ts +++ b/src/storage/conversion/ConversionUtil.ts @@ -1,6 +1,41 @@ +import fetch from 'cross-fetch'; +import { readJsonSync } from 'fs-extra'; +import type { IJsonLdContext } from 'jsonld-context-parser'; +import { FetchDocumentLoader } from 'jsonld-context-parser'; import type { ValuePreference, ValuePreferences } from '../../http/representation/RepresentationPreferences'; import { INTERNAL_ALL } from '../../util/ContentTypes'; import { InternalServerError } from '../../util/errors/InternalServerError'; +import { resolveAssetPath } from '../../util/PathUtil'; + +/** + * First, checks whether a context is stored locally before letting the super class do a fetch. + * This can be used when converting JSON-LD with Comunica-related libraries, such as `rdf-parse`. + * + * To use this, add this document loader to the options of the call + * using the `KeysRdfParseJsonLd.documentLoader.name` key. + * All extra keys get passed in the Comunica ActionContext + * and this is the key that is used to define the document loader. + * See https://github.com/rubensworks/rdf-parse.js/blob/master/lib/RdfParser.ts + * and https://github.com/comunica/comunica/blob/master/packages/actor-rdf-parse-jsonld/lib/ActorRdfParseJsonLd.ts + */ +export class ContextDocumentLoader extends FetchDocumentLoader { + private readonly contexts: Record; + + public constructor(contexts: Record) { + super(fetch); + this.contexts = {}; + for (const [ key, path ] of Object.entries(contexts)) { + this.contexts[key] = readJsonSync(resolveAssetPath(path)); + } + } + + public async load(url: string): Promise { + if (url in this.contexts) { + return this.contexts[url]; + } + return super.load(url); + } +} /** * Cleans incoming preferences to prevent unwanted behaviour. diff --git a/src/storage/conversion/RdfToQuadConverter.ts b/src/storage/conversion/RdfToQuadConverter.ts index 1a8839c88..0de460b85 100644 --- a/src/storage/conversion/RdfToQuadConverter.ts +++ b/src/storage/conversion/RdfToQuadConverter.ts @@ -1,44 +1,18 @@ import { PassThrough } from 'stream'; import { KeysRdfParseJsonLd } from '@comunica/context-entries'; import type { NamedNode } from '@rdfjs/types'; -import fetch from 'cross-fetch'; -import { readJsonSync } from 'fs-extra'; -import { FetchDocumentLoader } from 'jsonld-context-parser'; -import type { IJsonLdContext } from 'jsonld-context-parser'; import rdfParser from 'rdf-parse'; import { BasicRepresentation } from '../../http/representation/BasicRepresentation'; import type { Representation } from '../../http/representation/Representation'; import { RepresentationMetadata } from '../../http/representation/RepresentationMetadata'; import { INTERNAL_QUADS } from '../../util/ContentTypes'; import { BadRequestHttpError } from '../../util/errors/BadRequestHttpError'; -import { resolveAssetPath } from '../../util/PathUtil'; import { pipeSafely } from '../../util/StreamUtil'; import { PREFERRED_PREFIX_TERM, SOLID_META } from '../../util/Vocabularies'; import { BaseTypedRepresentationConverter } from './BaseTypedRepresentationConverter'; +import { ContextDocumentLoader } from './ConversionUtil'; import type { RepresentationConverterArgs } from './RepresentationConverter'; -/** - * First checks if a context is stored locally before letting the super class do a fetch. - */ -class ContextDocumentLoader extends FetchDocumentLoader { - private readonly contexts: Record; - - public constructor(contexts: Record) { - super(fetch); - this.contexts = {}; - for (const [ key, path ] of Object.entries(contexts)) { - this.contexts[key] = readJsonSync(resolveAssetPath(path)); - } - } - - public async load(url: string): Promise { - if (url in this.contexts) { - return this.contexts[url]; - } - return super.load(url); - } -} - /** * Converts most major RDF serializations to `internal/quads`. * @@ -63,10 +37,6 @@ export class RdfToQuadConverter extends BaseTypedRepresentationConverter { const rawQuads = rdfParser.parse(representation.data, { contentType: representation.metadata.contentType!, baseIRI: identifier.path, - // All extra keys get passed in the Comunica ActionContext - // and this is the key that is used to define the document loader. - // See https://github.com/rubensworks/rdf-parse.js/blob/master/lib/RdfParser.ts - // and https://github.com/comunica/comunica/blob/master/packages/actor-rdf-parse-jsonld/lib/ActorRdfParseJsonLd.ts [KeysRdfParseJsonLd.documentLoader.name]: this.documentLoader, } as any) // This works only for those cases where the data stream has been completely read before accessing the metadata.