@muze-nl/oldm-core
v0.7.1
Published
Core Object - Linked Data Mapper, without parser or writer dependencies
Readme
@muze-nl/oldm-core
Core Object Linked Data Mapper package.
This package contains the object/graph mapping layer only. It has explicit ESM exports, no bundled parser/writer, no N3 dependency, and no global side effects.
import oldm, { one, many, first, Collection } from '@muze-nl/oldm-core'
import { n3Parser, n3PatchWriter, n3Writer } from '@muze-nl/oldm-n3'
const context = oldm({
parser: n3Parser,
writer: n3Writer,
patchWriter: n3PatchWriter
})Prefix preference
OLDM shortens predicate and type IRIs with the prefixes configured on the context. Prefix declarations found in Turtle input are parser conveniences; they do not decide the JavaScript property names exposed by OLDM.
When multiple prefixes point at the same namespace, client-provided prefixes are preferred over OLDM defaults, and defaults are preferred over prefixes found in a parsed source document. For example, both pim: and space: are common aliases for http://www.w3.org/ns/pim/space#. Since OLDM prefers space for that namespace, profile data using either pim:storage or space:storage is exposed as space$storage in JavaScript.
const context = oldm({
parser: n3Parser,
prefixes: {
space: 'http://www.w3.org/ns/pim/space#'
}
})
const profile = context.parse(turtle, profileUrl, 'text/turtle')
const me = profile.subjects[`${profileUrl}#me`]
console.log(me.space$storage.id)Multiple graphs in one context
Context keeps a registry of parsed graphs and exposes a combined view over all graphs loaded into the same context.
const profile = context.parse(profileTurtle, profileUrl, 'text/turtle')
const settings = context.parse(settingsTurtle, settingsUrl, 'text/turtle')
profile.get(`${profileUrl}#me`) // graph-specific view
context.get(`${profileUrl}#me`) // combined context view
context.graphs // parsed graphs in load order
context.graph(profileUrl) // graph by source URL
context.data // combined subjects
context.subjects // combined subject map
context.sources(context.get(`${profileUrl}#me`))
// graphs containing that subject
context.sources(context.get(`${profileUrl}#me`), 'vcard$fn')
// graphs containing that property
context.sources(context.get(`${profileUrl}#me`), 'vcard$fn', 'Auke')
// graphs containing that specific value
profile.context.data // same combined view, starting from a graph
profile.context.subjects // same combined subject map, starting from a graphThe combined context view merges named subjects by IRI. Graph-specific views remain unchanged, so code can still separate data by original resource. Blank nodes remain graph-scoped.
If a loader or middleware gives you a Graph, use graph.context to access the combined view for all graphs loaded into the same context:
const graph = context.parse(profileTurtle, profileUrl, 'text/turtle')
graph.data // subjects from this one resource
graph.context.data // combined subjects from the whole context
graph.context.get(id) // merged subject from the whole contextFor source-aware writes, use the graph-specific helpers when you know the resource you want to edit:
profile.set(`${profileUrl}#me`, 'vcard$fn', 'Auke')
profile.add(`${profileUrl}#me`, 'schema$knowsAbout', 'Linked Data')
profile.delete(`${profileUrl}#me`, 'schema$knowsAbout', 'Old value')Context-level helpers can choose a graph explicitly:
context.set(`${profileUrl}#me`, 'vcard$fn', 'Auke', { graph: profile })
context.add(`${profileUrl}#me`, 'schema$knowsAbout', 'Solid', { graph: profileUrl })When no graph is passed, context.set/add/delete() uses a conservative default: the subject's exact graph URL, the subject document URL without a fragment, the only graph that currently contains the subject, the configured defaultGraph, or the only graph in the context. Direct property assignment on a named subject from context.get(...) uses the same resolver, so simple edits can stay object-like:
const me = context.get(`${profileUrl}#me`)
me.vcard$fn = 'Auke'
delete me.vcard$nicknameIf there is no obvious source graph, OLDM throws and asks you to choose one explicitly with context.set/add/delete(..., { graph }) or graph.set/add/delete(...).
PATCH output
Graph#patch() delegates to the configured patchWriter, just like Graph#write() delegates to writer. Core stays parser/writer agnostic; use n3PatchWriter from @muze-nl/oldm-n3 when you want Solid N3 Patch output.
Patch writers can support owned anonymous values conservatively: fresh blank nodes and RDF collections can be inserted, while changed or deleted existing anonymous values are replaced as complete closures. Shared or cyclic anonymous values should fall back to full document replacement.
Public exports
- default
oldm(options)context factory ContextGraphNamedNodeBlankNodeCollectionone(values, whichOne)many(values)first(...values)prefixesrdfType
License
MIT.
