UNPKG

tripledoc

Version:

Library to read, create and update documents on a Solid Pod

848 lines (834 loc) 34.9 kB
import { Literal, BlankNode, Quad } from 'rdf-js'; import { DataFactory } from './n3dataset'; import { Reference, isLiteral, LiteralTypes, isReference, isStringLiteral, isIntegerLiteral, isDecimalLiteral, DateTimeLiteral, isDateTimeLiteral, IntegerLiteral, DecimalLiteral, StringLiteral, isBlankNode, generateLocaleTypeGuard, LocaleStringLiteral, } from './index'; import { findObjectsInDataset } from './getEntities'; import { BareTripleDocument, isSavedToPod } from './document'; import { initialiseDataset } from './n3dataset'; /** * Represents a single Subject in a [[TripleDocument]]. * * Used to read and modify properties of a single Subject in a [[TripleDocument]], using the `get*`, * `set*`, `add*` and `remove*` methods for the relevant data types. Note that those changes will * not be persisted until you call [[TripleDocument.save]]. */ export interface TripleSubject { /** * @returns The [[TripleDocument]] that contains this Subject. */ getDocument: () => BareTripleDocument; /** * @deprecated * @ignore This is mostly a convenience function to make it easy to work with n3 and tripledoc * simultaneously. If you rely on this, it's probably best to either file an issue * describing what you want to do that Tripledoc can't do directly, or to just use n3 * directly. * @returns The Triples pertaining to this Subject that are stored on the user's Pod. Note that * this does not return Triples that have not been saved yet - see * [[getPendingTriples]] for those. */ getTriples: () => Quad[]; /** * Find a literal string value for `predicate` on this Subject. * * This retrieves _one_ string literal, or `null` if none is found. If you want to find _all_ * string literals for a predicate, see [[getAllStrings]]. * * @param getString.predicate Which property of this Subject you want the value of. * @returns The first literal string value satisfying `predicate`, if any, and `null` otherwise. */ getString: (predicate: Reference) => string | null; /** * Find a literal string value in a given locale for `predicate` on this Subject. * * This retrieves _one_ string literal, or `null` if none (in the given locale) is found. If you * want to find _all_ string literals in a locale for a predicate, see [[getAllLocaleStrings]]. * * @param getLocaleString.predicate Which property of this Subject you want the value of. * @param getLocaleString.locale Which locale the string should be in, e.g. 'nl-NL'. * @returns The first literal string value satisfying `predicate` in the given locale, if any, and `null` otherwise. */ getLocaleString: (predicate: Reference, locale: string) => string | null; /** * Find a literal integer value for `predicate` on this Subject. * * This retrieves _one_ integer literal, or `null` if none is found. If you want to find _all_ * integer literals for a predicate, see [[getAllIntegers]]. * * @param getInteger.predicate Which property of this Subject you want the value of. * @returns The first literal integer value satisfying `predicate`, if any, and `null` otherwise. */ getInteger: (predicate: Reference) => number | null; /** * Find a literal decimal value for `predicate` on this Subject. * * This retrieves _one_ decimal literal, or `null` if none is found. If you want to find _all_ * decimal literals for a predicate, see [[getAllDecimals]]. * * @param getDecimal.predicate Which property of this Subject you want the value of. * @returns The first literal decimal value satisfying `predicate`, if any, and `null` otherwise. */ getDecimal: (predicate: Reference) => number | null; /** * Find a literal date+time value for `predicate` on this Subject. * * This retrieves _one_ date+time literal, or `null` if none is found. If you want to find _all_ * date+time literals for a predicate, see [[getAllDateTimes]]. * * @param getDateTime.predicate Which property of this Subject you want the value of. * @returns The first literal Date value satisfying `predicate`, if any, and `null` otherwise. */ getDateTime: (predicate: Reference) => Date | null; /** * @param getLiteral.predicate Which property of this Subject you want the value of. * @returns The first literal value satisfying `predicate`, if any, and `null` otherwise. * @deprecated This method has been superseded by the type-specific methods [[getString]], * [[getInteger]], [[getDecimal]] and [[getDateTime]]. */ getLiteral: (predicate: Reference) => LiteralTypes | null; /** * @param getAllStrings.predicate Which property of this Subject you want the values of. * @returns All literal string values satisfying `predicate`. */ getAllStrings: (predicate: Reference) => string[]; /** * @param getAllLocaleStrings.predicate Which property of this Subject you want the values of. * @param getAllLocaleStrings.locale Which locale the values should be in, e.g. 'nl-NL', or `undefined` to get all locale strings. * @returns All literal string values satisfying `predicate` in the given locale, or all locale strings if no locale was specified. */ getAllLocaleStrings: (predicate: Reference, locale?: string) => GetAllLocaleStringsReturnType<typeof locale>; /** * @param getAllIntegers.predicate Which property of this Subject you want the values of. * @returns All literal integer values satisfying `predicate`. */ getAllIntegers: (predicate: Reference) => number[]; /** * @param getAllDecimals.predicate Which property of this Subject you want the values of. * @returns All literal decimal values satisfying `predicate`. */ getAllDecimals: (predicate: Reference) => number[]; /** * @param getAllDateTimes.predicate Which property of this Subject you want the values of. * @returns All literal DateTime values satisfying `predicate`. */ getAllDateTimes: (predicate: Reference) => Date[]; /** * @param getAllLiterals.predicate Which property of this Subject you want the values of. * @returns All literal values satisfying `predicate`. * @deprecated This method has been superseded by the type-specific methods [[getAllStrings]], * [[getAllIntegers]], [[getAllDecimals]] and [[getAllDates]]. */ getAllLiterals: (predicate: Reference) => LiteralTypes[]; /** * Find a local Subject (i.e. without its own URL) referenced by this Subject with `predicate`. * * This retrieves _one_ [[TripleSubject]], or `null` if none is found. If you want to find _all_ * local Subjects for a predicate, see [[getAllLocalSubjects]]. * * @param getRef.predicate Which property of this Subject you want the value of. * @returns The first referenced local Subject satisfying `predicate`, if any, and `null` otherwise. * @ignore Experimental API; could change in minor or patch releases. */ getLocalSubject: (predicate: Reference) => TripleSubject | null; /** * Find local Subject (i.e. without their own URLs) referenced by this Subject with `predicate`. * * @param getRef.predicate Which property of this Subject you want the values of. * @returns All referenced local Subjects satisfying `predicate`. * @ignore Experimental API; could change in minor or patch releases. */ getAllLocalSubjects: (predicate: Reference) => Array<TripleSubject>; /** * Find a reference attached to this Subject with `predicate`. * * This retrieves _one_ reference, or `null` if none is found. If you want to find _all_ * references for a predicate, see [[getAllRefs]]. * * @param getRef.predicate Which property of this Subject you want the value of. * @returns The first referenced IRI satisfying `predicate`, if any, and `null` otherwise. */ getRef: (predicate: Reference) => Reference | null; /** * @ignore Deprecated method. * @deprecated Replaced by [[getRef]]. */ getNodeRef: (predicate: Reference) => Reference | null; /** * @returns The type of this Subject, if known. */ getType: () => Reference | null; /** * @param getAllRefs.predicate Which property of this Subject you want the values of. * @returns All references satisfying `predicate`. */ getAllRefs: (predicate: Reference) => Array<Reference>; /** * @ignore Deprecated method. * @deprecated Replaced by [[getAllRefs]]. */ getAllNodeRefs: (predicate: Reference) => Array<Reference>; /** * Set a property of this Subject to a Literal string value. * * Note that this value is not saved to the user's Pod until you save the containing Document. * * @param addString.predicate The property you want to add another value of. * @param addString.object The Literal string value you want to add. */ addString: (predicate: Reference, object: string) => void; /** * Set a property of this Subject to a Literal localised string value. * * Note that this value is not saved to the user's Pod until you save the containing Document. * * @param addLocaleString.predicate The property you want to add another value of. * @param addLocaleString.object The Literal string value you want to add. * @param addLocaleString.locale The locale the given string is in. */ addLocaleString: (predicate: Reference, object: string, locale: string) => void; /** * Set a property of this Subject to a Literal integer value. * * Note that this value is not saved to the user's Pod until you save the containing Document. * * @param addInteger.predicate The property you want to add another value of. * @param addInteger.object The Literal integer value you want to add. */ addInteger: (predicate: Reference, object: number) => void; /** * Set a property of this Subject to a Literal decimal value. * * Note that this value is not saved to the user's Pod until you save the containing Document. * * @param addDecimal.predicate The property you want to add another value of. * @param addDecimal.object The Literal decimal value you want to add. */ addDecimal: (predicate: Reference, object: number) => void; /** * Set a property of this Subject to a Literal DateTime value. * * Note that this value is not saved to the user's Pod until you save the containing Document. * * @param addDateTime.predicate The property you want to add another value of. * @param addDateTime.object The Literal DateTime value you want to add. */ addDateTime: (predicate: Reference, object: Date) => void; /** * Set a property of this Subject to a Literal value (i.e. not a URL). * * Note that this value is not saved to the user's Pod until you save the containing Document. * * @param addLiteral.predicate The property you want to add another value of. * @param addLiteral.object The Literal value you want to add, the type of which is one of [[LiteralTypes]]. * @deprecated This method has been superseded by the type-specific methods [[addString]], * [[addInteger]], [[addDecimal]] and [[addDateTime]]. */ addLiteral: (predicate: Reference, object: LiteralTypes) => void; /** * Set a property of this Subject to a [[Reference]]. * * Note that this value is not saved to the user's Pod until you save the containing Document. * * @param addRef.predicate The property you want to add another value of. * @param addRef.object The IRI you want to add a reference to. */ addRef: (predicate: Reference, object: Reference) => void; /** * @ignore Deprecated method. * @deprecated Replaced by [[addRef]]. */ addNodeRef: (predicate: Reference, object: Reference) => void; /** * Remove a Literal string value for a property of this Subject. * * Note that this value is not removed from the user's Pod until you save the containing Document. * * @param removeString.predicate The property you want to remove a value of. * @param removeString.object The Literal string value you want to remove. */ removeString: (predicate: Reference, object: string) => void; /** * Remove a Literal localised string value for a property of this Subject. * * Note that this value is not removed from the user's Pod until you save the containing Document. * * @param removeLocaleString.predicate The property you want to remove a value of. * @param removeLocaleString.object The Literal string value you want to remove. * @param removeLocaleString.locale The locale of the string to remove. */ removeLocaleString: (predicate: Reference, object: string, locale: string) => void; /** * Remove a Literal integer value for a property of this Subject. * * Note that this value is not removed from the user's Pod until you save the containing Document. * * @param removeInteger.predicate The property you want to remove a value of. * @param removeInteger.object The Literal integer value you want to remove. */ removeInteger: (predicate: Reference, object: number) => void; /** * Remove a Literal decimal value for a property of this Subject. * * Note that this value is not removed from the user's Pod until you save the containing Document. * * @param removeDecimal.predicate The property you want to remove a value of. * @param removeDecimal.object The Literal decimal value you want to remove. */ removeDecimal: (predicate: Reference, object: number) => void; /** * Remove a Literal DateTime value for a property of this Subject. * * Note that this value is not removed from the user's Pod until you save the containing Document. * * @param removeDateTime.predicate The property you want to remove a value of. * @param removeDateTime.object The Literal DateTime value you want to remove. */ removeDateTime: (predicate: Reference, object: Date) => void; /** * Remove a Literal value for a property of this Subject. * * Note that this value is not removed from the user's Pod until you save the containing Document. * * @param removeLiteral.predicate The property you want to remove a value of. * @param removeLiteral.object The Literal value you want to remove, the type of which is one of [[LiteralTypes]]. * @deprecated This method has been superseded by the type-specific methods [[removeString]], * [[removeInteger]], [[removeDecimal]] and [[removeDateTime]]. */ removeLiteral: (predicate: Reference, object: LiteralTypes) => void; /** * Remove a [[Reference]] value for a property of this Subject. * * Note that this pointer is not removed from the user's Pod until you save the containing Document. * * @param removeRef.predicate The property you want to remove a reference for. * @param removeRef.object The reference you want to remove. */ removeRef: (predicate: Reference, object: Reference) => void; /** * @ignore Deprecated. * @deprecated Replaced by [[removeRef]]. */ removeNodeRef: (predicate: Reference, object: Reference) => void; /** * Remove all values for a property of this Subject. * * Note that these values are not removed from the user's Pod until you save the containing * Document. * * @param removeAll.predicate The property you want to remove the values of. */ removeAll: (predicate: Reference) => void; /** * Set a property of this Subject to a string Literal value, clearing all existing values. * * Note that this change is not saved to the user's Pod until you save the containing Document. * * @param setString.predicate The property you want to set the value of. * @param setString.object The string Literal value you want to set. */ setString: (predicate: Reference, object: string) => void; /** * Set a property of this Subject to a localised string Literal value, clearing all existing values. * * Note that this change is not saved to the user's Pod until you save the containing Document. * * @param setLocaleString.predicate The property you want to set the value of. * @param setLocaleString.object The string Literal value you want to set. * @param setLocaleString.locale The locale of the given string. */ setLocaleString: (predicate: Reference, object: string, locale: string) => void; /** * Set a property of this Subject to an integer Literal value, clearing all existing values. * * Note that this change is not saved to the user's Pod until you save the containing Document. * * @param setInteger.predicate The property you want to set the value of. * @param setInteger.object The integer Literal value you want to set. */ setInteger: (predicate: Reference, object: number) => void; /** * Set a property of this Subject to a decimal Literal value, clearing all existing values. * * Note that this change is not saved to the user's Pod until you save the containing Document. * * @param setDecimal.predicate The property you want to set the value of. * @param setDecimal.object The decimal Literal value you want to set. */ setDecimal: (predicate: Reference, object: number) => void; /** * Set a property of this Subject to a DateTime Literal value, clearing all existing values. * * Note that this change is not saved to the user's Pod until you save the containing Document. * * @param setDateTime.predicate The property you want to set the value of. * @param setDateTime.object The DateTime Literal value you want to set. */ setDateTime: (predicate: Reference, object: Date) => void; /** * Set a property of this Subject to a Literal value, clearing all existing values. * * Note that this change is not saved to the user's Pod until you save the containing Document. * * @param setLiteral.predicate The property you want to set the value of. * @param setLiteral.object The Literal value you want to set, the type of which is one of [[LiteralTypes]]. * @deprecated This method has been superseded by the type-specific methods [[setString]], * [[setInteger]], [[setDecimal]] and [[setDateTime]]. */ setLiteral: (predicate: Reference, object: LiteralTypes) => void; /** * Set a property of this Subject to a [[Reference]], clearing all existing values. * * Note that this change is not saved to the user's Pod until you save the containing Document. * * @param setRef.predicate The property you want to set the value of. * @param setRef.object The reference you want to add. */ setRef: (predicate: Reference, object: Reference) => void; /** * @ignore Deprecated. * @deprecated Replaced by [[setRef]]. */ setNodeRef: (predicate: Reference, object: Reference) => void; /** * Unset all values for all Predicates of this Subject. * * @internal Currently an internal API for use by [[TripleDocument]]. */ clear: () => void; /** * @internal Pending Triples are only provided so the Document can access them in order to save * them - this is not part of the public API and can thus break in a minor release. * @returns A tuple with the first element being a list of Triples that should be deleted from * the store, and the second element a list of Triples that should be added to it. */ getPendingTriples: () => [Quad[], Quad[]]; /** * Get the IRI of the [[Reference]] representing this specific Subject. * * @returns The IRI of this specific Subject. */ asRef: () => Reference; /** * @ignore Deprecated. * @deprecated Replaced by [[asRef]]. */ asNodeRef: () => Reference; }; type StringWithLocale = { locale: string; value: string }; type GetAllLocaleStringsReturnType<X extends string | undefined> = X extends string ? string [] : Array<StringWithLocale>; /** * @internal Only to be called by the Document containing this subject; not a public API. * @param document The Document this Subject is defined in. * @param subjectRef The URL that identifies this subject. */ export function initialiseSubject(document: BareTripleDocument, subjectRef: Reference| BlankNode): TripleSubject { const subjectNode = isBlankNode(subjectRef) ? subjectRef : DataFactory.namedNode(subjectRef); const triples = (isSavedToPod(document)) ? document.getStore().match(subjectNode, null, null, null).toArray() : []; const dataset = initialiseDataset(); dataset.addAll(triples); let pendingAdditions: Quad[] = []; let pendingDeletions: Quad[] = []; const get = (predicateNode: Reference) => findObjectsInDataset(dataset, subjectRef, predicateNode); const getString = (predicateNode: Reference) => { const objects = get(predicateNode); const firstStringLiteral = objects.find(isStringLiteral); if (typeof firstStringLiteral === 'undefined') { return null; } return firstStringLiteral.value; }; const getLocaleString = (predicateNode: Reference, locale: string) => { const objects = get(predicateNode); const firstStringLiteral = objects.find(generateLocaleTypeGuard(locale)); if (typeof firstStringLiteral === 'undefined') { return null; } return firstStringLiteral.value; }; const getInteger = (predicateRef: Reference) => { const objects = get(predicateRef); const firstIntegerLiteral = objects.find(isIntegerLiteral); if (typeof firstIntegerLiteral === 'undefined') { return null; } return fromIntegerLiteral(firstIntegerLiteral); }; const getDecimal = (predicateRef: Reference) => { const objects = get(predicateRef); const firstDecimalLiteral = objects.find(isDecimalLiteral); if (typeof firstDecimalLiteral === 'undefined') { return null; } return fromDecimalLiteral(firstDecimalLiteral); }; const getDateTime = (predicateRef: Reference) => { const objects = get(predicateRef); const firstDateTimeLiteral = objects.find(isDateTimeLiteral); if (typeof firstDateTimeLiteral === 'undefined') { return null; } return fromDateTimeLiteral(firstDateTimeLiteral); }; const getLiteral = (predicateRef: Reference) => { const objects = get(predicateRef); const firstLiteral = objects.find(isLiteral); if (typeof firstLiteral === 'undefined') { return null; } return fromLiteral(firstLiteral); }; const getAllStrings = (predicateRef: Reference) => { const objects = get(predicateRef); const literals = objects.filter(isStringLiteral); return literals.map(fromStringLiteral); }; const getAllLocaleStrings = (predicateRef: Reference, locale?: string) => { const objects = get(predicateRef); if(locale) { const literals = objects.filter(generateLocaleTypeGuard(locale)); return literals.map(fromStringLiteral); } const literals = objects.filter(hasLocale); return literals.map(fromLocaleStringLiteral); }; const getAllIntegers = (predicateRef: Reference) => { const objects = get(predicateRef); const literals = objects.filter(isIntegerLiteral); return literals.map(fromIntegerLiteral); }; const getAllDecimals = (predicateRef: Reference) => { const objects = get(predicateRef); const literals = objects.filter(isDecimalLiteral); return literals.map(fromDecimalLiteral); }; const getAllDateTimes = (predicateRef: Reference) => { const objects = get(predicateRef); const literals = objects.filter(isDateTimeLiteral); return literals.map(fromDateTimeLiteral); }; const getAllLiterals = (predicateRef: Reference) => { const objects = get(predicateRef); const literals = objects.filter(isLiteral); return literals.map(fromLiteral); }; const getLocalSubject = (predicateRef: Reference) => { const objects = get(predicateRef); const firstRef = objects.find(isBlankNode); if (typeof firstRef === 'undefined') { return null; } return initialiseSubject(document, firstRef); }; const getAllLocalSubjects = (predicateRef: Reference) => { const objects = get(predicateRef); const nodeRefs = objects.filter(isBlankNode); return nodeRefs.map((localSubject: BlankNode) => initialiseSubject(document, localSubject)); }; const getRef = (predicateRef: Reference) => { const objects = get(predicateRef); const firstRef = objects.find(isReference); if (typeof firstRef === 'undefined') { return null; } return firstRef; }; const getAllRefs = (predicateRef: Reference) => { const objects = get(predicateRef); const nodeRefs = objects.filter(isReference); return nodeRefs; }; const getType = () => { return getRef('http://www.w3.org/1999/02/22-rdf-syntax-ns#type'); } const addLiteral = (predicateRef: Reference, literal: LiteralTypes) => { pendingAdditions.push(DataFactory.triple( subjectNode, DataFactory.namedNode(predicateRef), asLiteral(literal), )); }; const addString = (predicateRef: Reference, literal: string) => { if (typeof literal !== 'string') { throw new Error('The given value is not a string.'); } return addLiteral(predicateRef, literal); }; const addLocaleString = (predicateRef: Reference, literal: string, locale: string) => { if (typeof literal !== 'string') { throw new Error('The given value is not a string.'); } pendingAdditions.push(DataFactory.triple( subjectNode, DataFactory.namedNode(predicateRef), DataFactory.literal(literal, locale), )); }; const addInteger = (predicateRef: Reference, literal: number) => { if (typeof literal !== 'number' || !Number.isInteger(literal)) { throw new Error('The given value is not an integer.'); } return addLiteral(predicateRef, literal); }; const addDecimal = (predicateRef: Reference, literal: number) => { if (typeof literal !== 'number') { throw new Error('The given value is not a decimal.'); } pendingAdditions.push(DataFactory.triple( subjectNode, DataFactory.namedNode(predicateRef), DataFactory.literal(literal.toString(), DataFactory.namedNode('http://www.w3.org/2001/XMLSchema#decimal')), )); }; const addDateTime = (predicateRef: Reference, literal: Date) => { if (literal instanceof Date === false) { throw new Error('The given value is not a DateTime.'); } return addLiteral(predicateRef, literal); }; const addRef = (predicateRef: Reference, nodeRef: Reference) => { pendingAdditions.push(DataFactory.triple( subjectNode, DataFactory.namedNode(predicateRef), DataFactory.namedNode(nodeRef), )); }; const removeRef = (predicateRef: Reference, nodeRef: Reference) => { pendingDeletions.push(DataFactory.triple( subjectNode, DataFactory.namedNode(predicateRef), DataFactory.namedNode(nodeRef), )); }; const removeLiteral = (predicateRef: Reference, literal: LiteralTypes) => { pendingDeletions.push(DataFactory.triple( subjectNode, DataFactory.namedNode(predicateRef), asLiteral(literal), )); }; const removeString = (predicateRef: Reference, literal: string) => { if (typeof literal !== 'string') { throw new Error('The given value is not a string.'); } return removeLiteral(predicateRef, literal); }; const removeLocaleString = (predicateRef: Reference, literal: string, locale: string) => { if (typeof literal !== 'string') { throw new Error('The given value is not a string.'); } pendingDeletions.push(DataFactory.triple( subjectNode, DataFactory.namedNode(predicateRef), DataFactory.literal(literal, locale), )); }; const removeInteger = (predicateRef: Reference, literal: number) => { if (typeof literal !== 'number' || !Number.isInteger(literal)) { throw new Error('The given value is not an integer.'); } return removeLiteral(predicateRef, literal); }; const removeDecimal = (predicateRef: Reference, literal: number) => { if (typeof literal !== 'number') { throw new Error('The given value is not a decimal.'); } // We cannot re-use `removeLiteral` here because it will parse `42.0` as an integer: pendingDeletions.push(DataFactory.triple( subjectNode, DataFactory.namedNode(predicateRef), DataFactory.literal(literal.toString(), DataFactory.namedNode('http://www.w3.org/2001/XMLSchema#decimal')), )); }; const removeDateTime = (predicateRef: Reference, literal: Date) => { if (literal instanceof Date === false) { throw new Error('The given value is not a DateTime.'); } return removeLiteral(predicateRef, literal); }; const removeAll = (predicateRef: Reference) => { pendingDeletions.push(...dataset.match( subjectNode, DataFactory.namedNode(predicateRef), null, null, ).toArray()); }; const clear = () => { pendingDeletions.push(...getTriples()); }; const setRef = (predicateRef: Reference, nodeRef: Reference) => { removeAll(predicateRef); addRef(predicateRef, nodeRef); }; const setLiteral = (predicateRef: Reference, literal: LiteralTypes) => { removeAll(predicateRef); addLiteral(predicateRef, literal); }; const setString = (predicateRef: Reference, literal: string) => { removeAll(predicateRef); addString(predicateRef, literal); }; const setLocaleString = (predicateRef: Reference, literal: string, locale: string) => { removeAll(predicateRef); addLocaleString(predicateRef, literal, locale); }; const setInteger = (predicateRef: Reference, literal: number) => { removeAll(predicateRef); addInteger(predicateRef, literal); }; const setDecimal = (predicateRef: Reference, literal: number) => { removeAll(predicateRef); addDecimal(predicateRef, literal); }; const setDateTime = (predicateRef: Reference, literal: Date) => { removeAll(predicateRef); addDateTime(predicateRef, literal); }; const getTriples = () => dataset.match( subjectNode, null, null, null, ).toArray(); const asRef = () => isBlankNode(subjectRef) ? subjectRef.value : subjectRef; const subject: TripleSubject = { getDocument: () => document, getTriples: getTriples, getString: getString, getLocaleString: getLocaleString, getInteger: getInteger, getDecimal: getDecimal, getDateTime: getDateTime, getLiteral: getLiteral, getAllStrings: getAllStrings, getAllLocaleStrings: getAllLocaleStrings, getAllIntegers: getAllIntegers, getAllDecimals: getAllDecimals, getAllDateTimes: getAllDateTimes, getAllLiterals: getAllLiterals, getLocalSubject: getLocalSubject, getAllLocalSubjects: getAllLocalSubjects, getRef: getRef, getAllRefs: getAllRefs, getType: getType, addString: addString, addLocaleString: addLocaleString, addInteger: addInteger, addDecimal: addDecimal, addDateTime: addDateTime, addRef: addRef, removeAll: removeAll, removeString: removeString, removeLocaleString: removeLocaleString, removeInteger: removeInteger, removeDecimal: removeDecimal, removeDateTime: removeDateTime, removeRef: removeRef, setRef: setRef, setString: setString, setLocaleString: setLocaleString, setInteger: setInteger, setDecimal: setDecimal, setDateTime: setDateTime, clear: clear, getPendingTriples: () => [pendingDeletions, pendingAdditions], asRef: asRef, // Deprecated aliases, included for backwards compatibility: getNodeRef: getRef, getAllNodeRefs: getAllRefs, addNodeRef: addRef, addLiteral: addLiteral, removeNodeRef: removeRef, removeLiteral: removeLiteral, setNodeRef: setRef, setLiteral: setLiteral, asNodeRef: asRef, }; return subject; } function fromDateTimeLiteral(literal: DateTimeLiteral): Date { // See https://github.com/linkeddata/rdflib.js/blob/d84af88f367b8b5f617c753d8241c5a2035458e8/src/literal.js#L87 const utcFullYear = parseInt(literal.value.substring(0, 4), 10); const utcMonth = parseInt(literal.value.substring(5, 7), 10) - 1; const utcDate = parseInt(literal.value.substring(8, 10), 10); const utcHours = parseInt(literal.value.substring(11, 13), 10); const utcMinutes = parseInt(literal.value.substring(14, 16), 10); const utcSeconds = parseInt(literal.value.substring(17, literal.value.indexOf('Z')), 10); const date = new Date(0); date.setUTCFullYear(utcFullYear); date.setUTCMonth(utcMonth); date.setUTCDate(utcDate); date.setUTCHours(utcHours); date.setUTCMinutes(utcMinutes); date.setUTCSeconds(utcSeconds); return date; } function fromIntegerLiteral(literal: IntegerLiteral): number { return parseInt(literal.value, 10); } function fromDecimalLiteral(literal: DecimalLiteral): number { return parseFloat(literal.value); } function fromStringLiteral(literal: StringLiteral | LocaleStringLiteral<string>): string { return literal.value; } function hasLocale(value: string | BlankNode | Literal): value is Literal { if(isLiteral(value)) { return value.language.length > 0; } return false; } function fromLocaleStringLiteral(value: Literal): StringWithLocale { return { locale: value.language, value: value.value } } function fromLiteral(literal: Literal): LiteralTypes { if (isDateTimeLiteral(literal)) { return fromDateTimeLiteral(literal); } if (isIntegerLiteral(literal)) { return fromIntegerLiteral(literal); } if (isDecimalLiteral(literal)) { return fromDecimalLiteral(literal); } return literal.value; } function asLiteral(literal: LiteralTypes): Literal { if (literal instanceof Date) { // To align with rdflib, we ignore miliseconds: // https://github.com/linkeddata/rdflib.js/blob/d84af88f367b8b5f617c753d8241c5a2035458e8/src/literal.js#L74 const roundedDate = new Date( Date.UTC( literal.getUTCFullYear(), literal.getUTCMonth(), literal.getUTCDate(), literal.getUTCHours(), literal.getUTCMinutes(), literal.getUTCSeconds(), 0, ), ); // Truncate the `.000Z` at the end (i.e. the miliseconds), to plain `Z`: const rdflibStyleString = roundedDate.toISOString().replace(/\.000Z$/, 'Z'); return DataFactory.literal(rdflibStyleString, DataFactory.namedNode('http://www.w3.org/2001/XMLSchema#dateTime')); } if (typeof literal === 'number' && Number.isInteger(literal)) { return DataFactory.literal(literal.toString(), DataFactory.namedNode('http://www.w3.org/2001/XMLSchema#integer')) } if (typeof literal === 'number' && !Number.isInteger(literal)) { return DataFactory.literal(literal.toString(), DataFactory.namedNode('http://www.w3.org/2001/XMLSchema#decimal')) } return DataFactory.literal(literal.toString()); }