Documentation
¶
Overview ¶
Package editor is the record-editing service surface: the JSON patch shape the API accepts, its validation against the editorial predicate whitelist, and the conversion to bibframe editorial patches. The typed WorkDoc mapper and operation lists layer on top in later tasks; this is the quad-level floor they compile down to.
Index ¶
Constants ¶
This section is empty.
Variables ¶
var DefaultPredicateAllowlist = []string{
"http://id.loc.gov/ontologies/bibframe/",
"http://id.loc.gov/ontologies/bflc/",
"https://github.com/freeeve/libcat/ns#",
"http://www.w3.org/2004/02/skos/core#",
"http://www.w3.org/2000/01/rdf-schema#label",
}
DefaultPredicateAllowlist is the editorial predicate policy when a deployment configures none: BIBFRAME descriptive predicates, libcat's lcat: extension markers, and SKOS term descriptions. A fully open editorial graph would let one bad request poison projector output.
Functions ¶
func ApplyOps ¶
func ApplyOps(m *Mapper, grainNQ []byte, workID string, ops []Op, labels LabelResolver) ([]byte, error)
ApplyOps edits a grain through the profile mapper, translating field operations into the editorial write shapes of ARCHITECTURE §5:
- Adding a value asserts it editorially (direct fields on the resource node; chained fields on a deterministic skolem IRI, since editorial statements cannot reference the feed's blank structure nodes).
- Removing an editorial value retracts its quad.
- Any edit that suppresses feed values (remove/set/clear touching them) claims the field with an lcat:overrides marker and re-asserts the surviving values editorially -- the tasks/042 semantics, so the feed stays untouched and revert is always possible.
Label companions (tasks/145): when labels is non-nil, every IRI the patch asserts on a prefLabel-annotated field also gets its vocabulary labels written into the grain's authority:<scheme> graph, so the grain stays self-describing (Duplicates compare, exports, the projection's label index) without a vocab lookup at read time -- feed parity with ingest.enrichmentQuads.
Returns the re-canonicalized grain.
Types ¶
type Diff ¶
Diff describes the exact grain change a patch would make (the dry-run / diff-preview payload): canonical N-Quads lines added and removed.
func ComputeDiff ¶
ComputeDiff applies the patch to a copy of the grain and reports the line-level delta between the canonical forms.
type FieldValue ¶
type FieldValue struct {
V string `json:"v"`
Lang string `json:"lang,omitempty"`
// Datatype preserves a literal's explicit datatype IRI.
Datatype string `json:"datatype,omitempty"`
// IRI marks an entity-valued field (V is the IRI).
IRI bool `json:"iri,omitempty"`
// Prov is the named graph the value came from ("feed:overdrive",
// "editorial:", "enrichment:locsh").
Prov string `json:"prov"`
// Overridden marks feed values shadowed by an lcat:overrides marker
// (tasks/042).
Overridden bool `json:"overridden,omitempty"`
// Annotation is the field's display-only qualifier resolved from the
// value's structure node (e.g. a heading's bf:source label, a
// contribution's bf:role label). Its quads stay in passthrough; ToGrain
// ignores it.
Annotation string `json:"annotation,omitempty"`
// Primary marks a chained value whose structure head is typed
// bflc:PrimaryContribution (tasks/138) -- the author sorts before the
// narrator. Display-only; ToGrain ignores it.
Primary bool `json:"primary,omitempty"`
// Node is the value's subject term in N-Quads syntax -- the resource
// node for direct fields, the intermediate node for chained fields.
// Reconstruction metadata; clients treat it as opaque.
Node string `json:"node"`
}
FieldValue is one value of a profile field, with provenance for the editor's badges and the reconstruction metadata (Node) that keeps the grain <-> doc mapping lossless.
type LabelResolver ¶
LabelResolver resolves a controlled-term IRI to its vocabulary scheme and language-tagged prefLabels ("" key = untagged); ok is false when no loaded vocabulary knows the IRI. vocab.Index.LabelResolver adapts the index; nil disables label companions.
type Mapper ¶
type Mapper struct {
// WorkProfile shapes the Work fields; InstanceProfile the Instances'.
WorkProfile *profiles.Profile
InstanceProfile *profiles.Profile
}
Mapper materializes grains through a profile pair.
func (*Mapper) ToDoc ¶
ToDoc decomposes a grain into the typed document for one of its Works. Every quad is either claimed by exactly one profile field (rendered as a FieldValue) or preserved verbatim in Passthrough. Feed values whose (subject, predicate) carries an editorial lcat:overrides marker come back flagged Overridden -- shadowed in projection, shown to the editor for the hover-reveal / revert affordance.
type Op ¶
type Op struct {
// Resource is "work" or an Instance id.
Resource string `json:"resource"`
// Path names the profile field.
Path string `json:"path"`
// Action: "add" one value, "remove" one matching value, "set" the whole
// value set, "clear" every value.
Action string `json:"action"`
Value *OpValue `json:"value,omitempty"` // add / remove
Values []OpValue `json:"values,omitempty"` // set
}
Op is one field-level edit. The SPA emits ordered op lists; the same shape backs drafts, macros, and batch templates (the plan's everything-is-an-operation-list rule).
type OpValue ¶
type OpValue struct {
V string `json:"v"`
Lang string `json:"lang,omitempty"`
IRI bool `json:"iri,omitempty"`
}
OpValue is one value in an operation.
type Patch ¶
type Patch struct {
Add []Statement `json:"add,omitempty"`
Remove []Statement `json:"remove,omitempty"`
}
Patch is the request body of a record edit: statements to add to and remove from the editorial graph.
func (Patch) ToBibframe ¶
ToBibframe converts the wire patch to a bibframe editorial patch.
type ResourceDoc ¶
type ResourceDoc struct {
ID string `json:"id"`
Fields map[string][]FieldValue `json:"fields"`
}
ResourceDoc is one resource's field view.
type Statement ¶
Statement is the JSON wire form of one editorial statement. Subjects are IRIs (typically "#<id>Work" / "#<id>Instance" fragments); objects are IRIs or literals -- never blank nodes, per the editorial-graph constraint.
type Term ¶
type Term struct {
// Kind is "iri" or "literal".
Kind string `json:"kind"`
Value string `json:"value"`
Lang string `json:"lang,omitempty"`
// Datatype is the literal datatype IRI, when not a plain/lang string.
Datatype string `json:"datatype,omitempty"`
}
Term is the JSON wire form of an RDF term.
type WorkDoc ¶
type WorkDoc struct {
WorkID string `json:"workId"`
ProfileID string `json:"profileId"`
Work ResourceDoc `json:"work"`
Instances []ResourceDoc `json:"instances"`
// Passthrough holds the unclaimed statements as raw N-Quads lines.
Passthrough []string `json:"passthrough"`
}
WorkDoc is the typed editing document one grain materializes into: the Work's profile fields, its Instances' fields, and a passthrough of every statement no field claims -- so doc -> grain reproduces the input byte-for-byte when nothing is edited.