npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@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 graph

The 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 context

For 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$nickname

If 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
  • Context
  • Graph
  • NamedNode
  • BlankNode
  • Collection
  • one(values, whichOne)
  • many(values)
  • first(...values)
  • prefixes
  • rdfType

License

MIT.