manifest

package
v0.3.0 Latest Latest
Warning

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

Go to latest
Published: Sep 28, 2026 License: MIT Imports: 12 Imported by: 0

Documentation

Overview

Package manifest reads the item files `pay plan` and `pay sync` execute (F6) and implements the pure half of the {"$ref": …} grammar every write body accepts: parsing a reference, finding every reference in a body, replacing them, and ordering plan items so a document is created before the items that point at it.

Nothing here talks to Payload. Resolving a reference to an id, matching an item against the server and diffing it are the command layer's job (internal/cli/plan.go, refs.go); this package only decides what the files say and whether that is well formed, so every rule is a table test.

Index

Constants

View Source
const (
	// RefKey marks an object as a reference.
	RefKey = "$ref"
	// AsKey selects the replacement's shape.
	AsKey = "$as"
	// WhereKey carries a Payload where object.
	WhereKey = "where"
	// AsID (the default) replaces the reference with the bare id.
	AsID = "id"
	// AsPolymorphic replaces it with {relationTo, value}, the shape of a
	// relationship whose relationTo lists several collections.
	AsPolymorphic = "polymorphic"
	// LocalPrefix starts a plan-local reference: "@key".
	LocalPrefix = "@"
)

The reference grammar. A reference is any JSON object with a "$ref" key, anywhere in a write body:

{"$ref": "pages", "slug": "about"}                   → 12
{"$ref": "pages", "slug": "about", "$as": "polymorphic"}
                                                     → {"relationTo":"pages","value":12}
{"$ref": "posts", "where": {"title": {"like": "x"}}} → a Payload where object
{"$ref": "@home"}                                    → the id of plan item "home"

Every key other than $ref, $as and where is an equals-match on that field (dotted keys reach group fields: "meta.title"). The value must be a scalar.

View Source
const DefaultMatch = "slug"

DefaultMatch is the match field an item without "match" uses.

Variables

This section is empty.

Functions

func HasRefs

func HasRefs(v any) bool

HasRefs is a cheap test: does v contain any reference at all?

func IsRef

func IsRef(v any) bool

IsRef reports whether v is a reference object.

func IsScalar

func IsScalar(v any) bool

IsScalar reports a JSON string, number or boolean.

func Lookup

func Lookup(body map[string]any, key string) (any, bool)

Lookup reads a possibly dotted key ("meta.title") from a body.

func Order

func Order(n int, deps map[int][]int) (order []int, cycle []int, ok bool)

Order sorts n items so that every item comes after the items it depends on. deps[i] lists the items i depends on. Among items that are ready at the same time the lowest index goes first, so an independent manifest keeps its load order exactly and the result is deterministic.

When the dependencies contain a cycle, Order returns ok=false and one cycle as a list of indices, first element repeated at the end ([a, b, a]), for the error message.

func Replace

func Replace(body map[string]any, resolve func(*Ref) (any, error)) (map[string]any, error)

Replace returns a deep copy of body with every reference replaced by resolve's answer. body is never mutated. The first error aborts.

func ScalarString

func ScalarString(v any) string

ScalarString renders a scalar for a key or a message.

Types

type Item

type Item struct {
	// Key names the item for "@key" references and in every report. It is
	// the manifest's "key", or derived: "<collection>/<match values…>" for a
	// collection item, "globals/<slug>" for a global.
	Key string `json:"key"`
	// KeyExplicit says the manifest set Key itself.
	KeyExplicit bool `json:"-"`
	// Collection or Global — exactly one is set.
	Collection string `json:"collection,omitempty"`
	Global     string `json:"global,omitempty"`
	// Match are the fields whose values (taken from Data) identify the
	// document. Collections only; default [DefaultMatch].
	Match []string `json:"match,omitempty"`
	// Status is keep, draft or published.
	Status Status `json:"status"`
	// Locale is the locale the item is matched, diffed and written in; ""
	// means the command's --locale / the profile's default.
	Locale string `json:"locale,omitempty"`
	// Data is the document body. It may hold {"$ref": …} objects.
	Data map[string]any `json:"-"`
	// File is the manifest file the item came from ("-" for stdin), and
	// Index its position in that file (0 for a single-object file).
	File  string `json:"file"`
	Index int    `json:"index"`
	// Multi says the file holds an array, so the item's label carries its
	// index.
	Multi bool `json:"-"`
	// FromEnvelope says the file was a PayCLI `pay get` / `pay globals get`
	// envelope rather than a manifest item.
	FromEnvelope bool `json:"-"`
}

Item is one entry of a manifest: one document or one global, and the data it must hold.

func Load

func Load(paths []string, stdin io.Reader) ([]*Item, error)

Load reads every item from the given paths. A directory contributes every *.json file below it (recursively, in lexical order, skipping names that start with "."); "-" reads one manifest from stdin. The result is in load order with keys derived and uniqueness checked. Every problem is collected before failing, so one run names all of them.

func (*Item) Label

func (it *Item) Label() string

Label is how an item is named where it came from: "dir/a.json" or "dir/list.json#2".

func (*Item) MatchValues

func (it *Item) MatchValues() (map[string]any, []string, error)

MatchValues returns the match fields and their values from Data, in Match order. ok is false when a value is missing, null or not a scalar.

func (*Item) Target

func (it *Item) Target() string

Target is "pages" or "global footer", for messages.

type Problem

type Problem struct {
	// Where is the item label ("dir/a.json#1") or file.
	Where string
	// Code is the apierr code this problem would raise on its own.
	Code apierr.Code
	// Message says what is wrong.
	Message string
	// Hint says what to do about it ("" = the code's default).
	Hint string
}

Problem is one thing wrong with a manifest, named by the item it concerns.

type Problems

type Problems []Problem

Problems is a manifest that cannot be planned. It converts to one manifest_invalid error naming every problem.

func (Problems) Err

func (ps Problems) Err() error

Err renders the problems as one error (nil when there are none). The code is the problems' common code when they share one, else manifest_invalid.

type Ref

type Ref struct {
	// Path is where in the body the reference sits (docdiff notation).
	Path string
	// Collection is the target collection; empty for a local reference.
	Collection string
	// Local is the plan item key of a "@key" reference (without the @).
	Local string
	// As is AsID or AsPolymorphic.
	As string
	// Equals are the equals-matches, sorted by field.
	Equals []Term
	// Where is the reference's own Payload where object, if any.
	Where map[string]any
}

Ref is one parsed reference.

func Collect

func Collect(v any) ([]*Ref, error)

Collect returns every reference in v, in document order (object keys sorted). A reference inside a reference is not looked for: its values are scalars by construction.

func Parse

func Parse(m map[string]any, path string) (*Ref, error)

Parse validates one reference object found at path.

func (*Ref) IsLocal

func (r *Ref) IsLocal() bool

IsLocal reports a plan-local "@key" reference.

func (*Ref) String

func (r *Ref) String() string

String renders the reference compactly for messages: `pages{slug=about}`, `@home`, `posts{where}`.

func (*Ref) Value

func (r *Ref) Value(collection string, id any) any

Value is what the reference is replaced with, once collection and id are known.

type Status

type Status string

Status is an item's "status": what the write does to the document's publication state on a drafts-enabled collection or global.

const (
	// StatusKeep (the default) leaves the publication state alone: a
	// document whose newest version is published is saved published (its
	// live content changes), one whose newest version is a draft gets a new
	// draft — including a published document with a pending draft, whose live
	// version stays as it is (warning saved_as_draft) — and a new document is
	// created as a draft.
	StatusKeep Status = "keep"
	// StatusDraft saves the change as a draft (?draft=true). It never
	// unpublishes: a published document keeps its live version and gets a
	// draft on top.
	StatusDraft Status = "draft"
	// StatusPublished writes _status "published": the result is live, and
	// Payload runs full validation.
	StatusPublished Status = "published"
)

type Term

type Term struct {
	Field string
	Value any
}

Term is one equals-match of a reference.

Jump to

Keyboard shortcuts

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