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
- func HasRefs(v any) bool
- func IsRef(v any) bool
- func IsScalar(v any) bool
- func Lookup(body map[string]any, key string) (any, bool)
- func Order(n int, deps map[int][]int) (order []int, cycle []int, ok bool)
- func Replace(body map[string]any, resolve func(*Ref) (any, error)) (map[string]any, error)
- func ScalarString(v any) string
- type Item
- type Problem
- type Problems
- type Ref
- type Status
- type Term
Constants ¶
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.
const DefaultMatch = "slug"
DefaultMatch is the match field an item without "match" uses.
Variables ¶
This section is empty.
Functions ¶
func Order ¶
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 ¶
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 ¶
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 ¶
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 ¶
Label is how an item is named where it came from: "dir/a.json" or "dir/list.json#2".
func (*Item) MatchValues ¶
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.
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.
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 ¶
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.
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" )