Documentation
¶
Overview ¶
Package nodedoc is the codec for a single node's portable file form — the frontmatter-markdown (and canonical JSON) representation that `hadron memory export`, `hadron node export`, and `hadron node import` all share.
It is deliberately decoupled from genqlient's generated types: the command layer maps a gen node to a Document (see api.DocumentFromBatchNode) and the codec maps a Document to and from bytes. Keeping the on-disk format pinned to this neutral struct means a GraphQL schema reshuffle can't ripple into the file format, and the encode/decode pair lives in one place so the round-trip invariant (parse∘render == identity) holds by construction.
Index ¶
- func ContentHash(content string) string
- func DecodeJSON(raw *json.RawMessage) any
- func EncodeJSON(v any) (*json.RawMessage, error)
- func MarshalYAML(v any) (string, error)
- func NodeFilePath(root, loc string) (string, error)
- func RenderJSON(doc *Document) (string, error)
- func RenderMarkdown(doc *Document, standalone bool) (string, error)
- type Document
- type Edge
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func ContentHash ¶
ContentHash recomputes the server's content fingerprint: sha256 of the content, hex, first 8 chars; empty content has no hash. Matches hadron-server's computeContentHash (src/lib/contentHash.ts) so an exported contentHash equals the value the server would have written. The GraphQL API does not expose the stored hash column, so the codec recomputes it.
func DecodeJSON ¶
func DecodeJSON(raw *json.RawMessage) any
DecodeJSON turns a GraphQL JSON scalar into a value yaml/json can render as a proper structure (not a quoted JSON string). A nil pointer, empty bytes, or a literal `null` decode to nil so a caller's omitempty drops the key.
func EncodeJSON ¶
func EncodeJSON(v any) (*json.RawMessage, error)
EncodeJSON is the inverse of DecodeJSON: it marshals a decoded value back to a GraphQL JSON scalar (json.RawMessage), returning nil for a nil value so the caller omits the field. Used to map a Document's Data/Properties/edge Condition into mutation inputs.
func MarshalYAML ¶
MarshalYAML encodes v as YAML with 2-space indents (matching the server's yaml writer) and trims the trailing newline so the caller controls the document framing.
func NodeFilePath ¶
NodeFilePath maps a loc to its on-disk markdown path under root. The empty-loc root node is README.md; every other node is <seg>/<seg>.md, so a node's path is stable whether or not it has children (children land in the sibling <seg>/ folder). Mirrors the server's nodeFilePath.
func RenderJSON ¶
RenderJSON emits the Document as a single pretty-printed JSON object — the canonical shape ParseJSON reads, so json↔json is trivially lossless and md↔json share the in-memory Document. HTML escaping is off so content with <, >, & stays literal. The output ends in a newline (json.Encoder framing).
contentHash is a derived field, recomputed from content (same as the markdown codec) on a copy so both formats agree and a hand-built or batch-read Document — whose ContentHash the GraphQL projection never carries — still serializes a correct hash without mutating the caller's value.
func RenderMarkdown ¶
RenderMarkdown produces the full node file: YAML frontmatter, then the node content as the body, framed as `---\n<fm>\n---\n\n<body>\n` (hadron-server's pushMemoryToGit file shape). When standalone is true the file carries its own loc/memory keys so a lone file is self-describing and re-importable without flags; a tree export passes false (loc lives in the path, memory in the sync target).
Types ¶
type Document ¶
type Document struct {
ID string `json:"id"`
MemoryURN string `json:"memory"`
Loc string `json:"loc"`
Name string `json:"name"`
Type string `json:"type"`
Alias string `json:"alias"`
Description string `json:"description"`
Abstract string `json:"abstract"`
AbstractOriginHash string `json:"abstractOriginHash"`
ContentHash string `json:"contentHash"`
Tags []string `json:"tags"`
Seq *int `json:"seq"`
Data any `json:"data"`
Properties any `json:"properties"`
Content string `json:"content"`
Edges []Edge `json:"edges"`
}
Document is the in-memory representation of one node that both directions of both codecs share. Optional string fields use "" for "absent" (the markdown codec omits them); Seq/Data/Properties use nil. NodeType "" means the server default (info) — it is never serialized, so a re-import defaults correctly.
func ParseJSON ¶
ParseJSON is the inverse of RenderJSON. Edges is normalized to a non-nil slice so a Document's shape is stable ([] not null) across the codecs.
func ParseMarkdown ¶
ParseMarkdown is the inverse of RenderMarkdown: it splits the frontmatter from the body, parses the YAML header, applies the `description ?? summary` legacy fallback, and trims the body. It accepts both a standalone single-node file (with loc/memory keys) and a tree-export file (without). A file with no `---` frontmatter is rejected.
type Edge ¶
type Edge struct {
TargetID string `json:"targetId"`
TargetLoc string `json:"targetLoc"`
Name string `json:"name"`
Loc string `json:"loc,omitempty"`
Description string `json:"description,omitempty"`
IsRunnable bool `json:"isRunnable,omitempty"`
Condition any `json:"condition"`
Priority int `json:"priority"`
}
Edge is one outgoing edge carried in a node's file. TargetLoc travels alongside TargetID for readability and as the portable key when re-homing a node into another memory, where the source TargetID no longer resolves. Name/Loc/Description/IsRunnable are the spec-037 first-class edge fields (Loc is the edge's own identity, distinct from TargetLoc). Condition and Priority round-trip the edge's gating and routing order.