Writes one entity to a SPARQL store as a single update request.

The request holds two operations that the store runs in one transaction:

  1. a DELETE … WHERE that removes the stored state of the entity: its own triples as far as schema describes them, and the anonymous (blank node) objects it owns. Named entities it links to are left alone. The WHERE is OPTIONAL, so the request also works for an entity that is not stored yet.
  2. an INSERT DATA with every triple of dataToBeSaved.

With skipRemove only the second operation is sent. With defaultUpdateGraph both operations address that named graph, otherwise the default graph.

The document cannot change the structure of the update, whatever it contains: values only ever become RDF terms, and a document that would produce an invalid term is refused. In detail, save throws if

  • an IRI, a datatype or a language tag is invalid, or a key is not mapped by the @context (the document is converted in strict mode),
  • the @context is given as a URL (it is never fetched),
  • the document addresses a named graph of its own through @graph,
  • @id, @type or defaultUpdateGraph is not a safe absolute IRI.

Blank node labels of the document are replaced by generated ones.

save inserts every triple the document expands to. It does not restrict them to the entity being saved:

  • a nested object with an @id of its own writes triples about that other entity, e.g. { "@id": "…/other", "isAdmin": true };
  • @reverse writes triples whose subject is another entity;
  • a property the schema does not know is written as well.

None of these are removed by the DELETE of a later save, which only covers the entity's own schema-described triples.

This is deliberately left to the caller. Which nested entities belong to a write is a decision about the data model, and save has no basis for it: writing a linked entity together with its parent is wanted in some places (bulk imports with skipRemove) and unwanted in others (a form save, where a linked entity must only be referenced). Whether a client may write to an entity at all is an authorization question that is outside this package.

A caller that takes documents from an untrusted source must therefore shape them first — cleanJSONLD from @graviola/jsonld-utils with pruneLinkedDocuments reduces a document to what the schema describes and turns linked entities into references; the SPARQL store implementation does this before every save.

if the document is refused (see above) or the store rejects the update

  • Parameters

    • dataToBeSaved: NamedAndTypedEntity

      the JSON-LD document, with @id, @type and an inline @context that maps all of its keys

    • schema: JSONSchema7

      JSON Schema of the entity; determines what the DELETE removes

    • updateFetch: (query: string) => Promise<any>

      sends the SPARQL update to the store

    • options: SaveOptions

      prefix, target graph, query build options, and optional maxRecursion for the DELETE (same depth as makeSPARQLDeleteQuery)

    Returns Promise<any>

    whatever updateFetch resolves to