nodedoc

package
v0.7.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 14, 2026 License: MIT Imports: 9 Imported by: 0

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

Constants

This section is empty.

Variables

This section is empty.

Functions

func ContentHash

func ContentHash(content string) string

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

func MarshalYAML(v any) (string, error)

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

func NodeFilePath(root, loc string) (string, error)

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

func RenderJSON(doc *Document) (string, error)

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

func RenderMarkdown(doc *Document, standalone bool) (string, error)

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

func ParseJSON(data []byte) (*Document, error)

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

func ParseMarkdown(data []byte) (*Document, error)

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.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL