cli

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: 56 Imported by: 0

Documentation

Overview

Package cli is PayCLI's command tree and the only place in the program that is allowed to see the process itself.

Everything ambient — argv, the environment, the three standard streams, the wall clock, the HTTP transport and the on-disk directory layout — enters through App and is carried to every command by Runtime. That is what makes whole-command golden tests possible in-process (§17.3): a test builds an App over bytes.Buffers and a fixture server's RoundTripper and asserts on the captured stdout, stderr and the returned exit code.

§3.1 makes this a CI-enforced rule: app.go is the only file outside cmd/ that may reference os.Stdout, os.Stderr, os.Stdin, os.Args, os.Getenv, os.Exit or time.Now.

Index

Constants

View Source
const (
	// WarnBackupSkipped names targeted documents the backup read did not
	// return. The write still runs — it will answer for those ids itself
	// (usually doc_not_found) — but nothing was saved for them.
	WarnBackupSkipped = "backup_skipped"
	// WarnBackupsOff is `pay backups …` run with no backup directory.
	WarnBackupsOff = "backups_disabled"
	// WarnBackupRedacted names the credential values a backup masked: the
	// file does not hold them, so a restore cannot bring them back.
	WarnBackupRedacted = "backup_redacted"
)

Warning codes raised by the backup hook.

View Source
const (
	// WarnRestoredAsDraft: the backup holds a draft, the live document is
	// published, so the restore saved a new draft instead of unpublishing.
	WarnRestoredAsDraft = "restored_as_draft"
	// WarnRecreatedNewID: --recreate made a new document; the id changed.
	WarnRecreatedNewID = "backup_recreated_new_id"
	// WarnRecreateIgnored: --recreate was passed but the document exists.
	WarnRecreateIgnored = "recreate_not_needed"
	// WarnFieldsNotRestored: fields the restore deliberately did not send.
	WarnFieldsNotRestored = "backup_fields_not_restored"
	// WarnRecreatedInTrash: the backup was of a trashed document, and so is
	// the re-created one.
	WarnRecreatedInTrash = "backup_recreated_in_trash"
	// WarnPublishedNotRestored: the backup holds a published state under a
	// newer draft, and this restore did not put it back.
	WarnPublishedNotRestored = "published_state_not_restored"
	// WarnRestoreTwoSteps: the dry run of a restore that writes the backup's
	// published state and then its draft on top — two versions.
	WarnRestoreTwoSteps = "restore_two_steps"
)

Warning codes `pay backups restore` raises.

View Source
const (
	// WarnNeverPublished marks a --draft-vs-published diff whose "published"
	// side is not a published document.
	WarnNeverPublished = "never_published"
	// WarnFieldNotOnDocument marks body keys the stored document does not
	// have — usually a typo, which Payload drops without an error.
	WarnFieldNotOnDocument = "field_not_on_document"
	// WarnBodyIDMismatch marks a body whose own id names another document.
	WarnBodyIDMismatch = "body_id_mismatch"
	// WarnBodyPublishes marks a body carrying _status "published": the write
	// publishes even when it is sent with --draft.
	WarnBodyPublishes = "body_publishes"
)

Warning codes `pay diff` raises.

View Source
const (
	CheckOK      = "ok"
	CheckWarn    = "warn"
	CheckFail    = "fail"
	CheckUnknown = "unknown"
	CheckSkipped = "skipped"
)

Check statuses. `unknown` is a first-class answer: a fact PayCLI could not establish is never reported as a pass or a failure (§7.6).

View Source
const (
	// DetailCap is how many per-collection detail entries the default tier
	// emits. The SLUG LIST IS NEVER TRUNCATED — data.collection_slugs always
	// holds every slug, because it is the single most load-bearing thing this
	// command returns.
	DetailCap = 40
	// DefaultMaxBytes is --max-bytes' default: above it, --full refuses.
	DefaultMaxBytes = 400 << 10
)

§18's tiers.

View Source
const (
	// WarnRedactedNotSent says masked values in merged fields were left out
	// of the body.
	WarnRedactedNotSent = "redacted_not_sent"
	// WarnRedactedRemoved says masked keys inside rich text or json had no
	// stored value to be restored from and were removed from the value.
	WarnRedactedRemoved = "redacted_removed"
)

Warning codes this file raises.

View Source
const (
	// WarnOrphanRows reports orphan symptoms observed after a write.
	WarnOrphanRows = "orphan_rows"
	// WarnOrphanRisk predicts them before a write.
	WarnOrphanRisk = "orphan_risk"
	// WarnEmptyRows reports `{}` rows in a document that was read.
	WarnEmptyRows = "empty_rows"
	// WarnOrphanCheckIncomplete says the stored row could not be read back
	// after the write, so orphan rows were neither confirmed nor ruled out.
	WarnOrphanCheckIncomplete = "orphan_check_incomplete"
	// WarnResetNestedNotNeeded says --reset-nested had nothing to do.
	WarnResetNestedNotNeeded = "reset_nested_not_needed"
	// WarnResetNestedIncomplete says a carrier phase failed after an earlier
	// one was written; the requested body was still written.
	WarnResetNestedIncomplete = "reset_nested_incomplete"
	// WarnPendingDraftSuperseded says a bulk non-draft write replaces
	// pending drafts instead of building on them (§10.2.3).
	WarnPendingDraftSuperseded = "pending_draft_superseded"
	// WarnResetNestedUnresolved names `{}` rows whose block type no version
	// of the document could name, so no carrier could clear them.
	WarnResetNestedUnresolved = "reset_nested_unresolved"
)

Warning codes of §10.2.1.

View Source
const (
	// WarnUpstreamError marks a stage that did nothing because its input was
	// already an error envelope.
	WarnUpstreamError = "upstream_error"
	// WarnBlocksFieldInferred marks a field chosen by looking at the document
	// rather than at the project's schema.
	WarnBlocksFieldInferred = "blocks_field_inferred"
	// WarnFieldAbsent marks a --field the document does not carry, which is
	// almost always a --select that trimmed it away.
	WarnFieldAbsent = "field_absent"
	// WarnPopulatedRelationship marks a row that carries an expanded
	// relationship object where the API expects an id.
	WarnPopulatedRelationship = "populated_relationship"
	// WarnEnvelopeUnwrapped marks a --data that was handed a whole PayCLI
	// envelope and was read as its .data.
	WarnEnvelopeUnwrapped = "envelope_unwrapped"
)

warn codes this file raises.

View Source
const (
	GroupDiscovery = "discovery"
	GroupRead      = "read"
	GroupWrite     = "write"
	GroupEdit      = "edit"
	GroupFiles     = "files"
	GroupAdmin     = "admin"
	GroupOther     = "other"
)

Command groups, so `pay --help` reads as a map of the tool rather than an alphabetical wall. A command that sets no GroupID lands in "other".

View Source
const (
	PathSourceBreadcrumbs = "breadcrumbs"
	PathSourceTemplate    = "template"
	PathSourceSlug        = "slug"
	PathSourceHome        = "home"
)

Path sources, in resolution order (F9).

View Source
const (
	WarnURLPathGuessed = "url_path_guessed"
	WarnURLNotLive     = "url_not_live"
	WarnPreviewNoAuth  = "preview_credential_withheld"
)

Warning codes `pay url` emits.

View Source
const CompletionBudget = 100 * time.Millisecond

CompletionBudget is §9.9's hard limit. A shell that hangs on TAB is worse than one that suggests nothing, so every completion function checks the budget before and after the one cache read it is allowed to make.

View Source
const CookieFilePerm = 0o600

CookieFilePerm is the preview cookie file's mode: the cookie IS draft access to the whole site for as long as the build lives.

View Source
const DefaultSlugField = "slug"

DefaultSlugField is the field ResolveDocBySlug matches when SlugLookup.Field is empty: the Payload website template's (and the slug field plugin's) name.

View Source
const (

	// WarnBlockTypeOmitted marks a `pay blocks add <blockType>` whose target
	// is a plain array field: the new row was added without the blockType.
	WarnBlockTypeOmitted = "block_type_omitted"
)
View Source
const WarnBodyStatusIgnored = "body_status_ignored"

WarnBodyStatusIgnored says a body's _status was removed: in upsert and sync the publication state is set by --draft/--publish (a manifest's "status") and nothing else. Leaving it in would reopen the body_publishes footgun — Payload publishes any write whose body says _status "published", ?draft=true notwithstanding (payload@3.87.1 collections/operations/ utilities/update.js, isSavingDraft).

View Source
const WarnConfigPathAnchored = "config_path_anchored"

WarnConfigPathAnchored: `pay config set` stored a relative path as the absolute path it means.

View Source
const WarnHookRewroteUnsent = "hook_rewrote_unsent"

WarnHookRewroteUnsent says a write changed fields the body declares but did not send (their value was already stored): a server hook fills fields a request leaves out.

View Source
const WarnMatchValueNormalized = "match_value_normalized"

WarnMatchValueNormalized says the server stored a match field in another form than the body sent (a slug-formatting hook): the next plan or upsert, which matches on the body's value, will not find the document.

View Source
const WarnPublishesPendingDraft = "publishes_pending_draft"

WarnPublishesPendingDraft says a write that publishes also publishes the document's pending draft (whose changes the caller may not have made).

View Source
const WarnRefTargetUnchecked = "ref_target_unchecked"

WarnRefTargetUnchecked says references sit in fields whose relationTo no schema source knows, so a reference naming the wrong collection could not be caught.

View Source
const WarnRelationIDNotNumeric = "relation_id_not_numeric"

WarnRelationIDNotNumeric says a {relationTo, value} pair names a document of a numeric-id collection by a value that is not a number: a Markdown link written as [text](pay:pages/about), where "about" is a slug.

View Source
const WarnSavedAsDraft = "saved_as_draft"

WarnSavedAsDraft says a write with status keep was saved into the pending draft of a published document: the live document did not change.

View Source
const WarnStaleIndex = "stale_index"

WarnStaleIndex marks a nested --field that enters a row BY POSITION of an array an earlier stage of the same pipe reordered or resized.

Variables

BulkExitCodes adds §12.5's partial commit and §12's confirmation gate. 7 is the one an agent must never auto-retry.

DestructiveExitCodes adds §12's confirmation gate to a single-document write.

ReadExitCodes is what any command that reads from the server can return.

View Source
var WriteExitCodes = ReadExitCodes

WriteExitCodes is ReadExitCodes for a single-document write: same failures, and nothing bulk-specific.

Functions

func CompleteBlockSlugs added in v0.2.0

func CompleteBlockSlugs(rt *Runtime) func(*cobra.Command, []string, string) ([]string, cobra.ShellCompDirective)

CompleteProfiles completes --profile from the two config files. It reads no credentials and never touches the keychain. CompleteBlockSlugs completes `pay describe <entity> --block <slug>` from the cached shard's block schemas and the cached block census (§7.10c) — on a project with introspection disabled the census is the only source of slugs.

It suggests the slugs, never the GraphQL interfaceNames: an interfaceName is exactly the value Payload silently drops (§7.10), so offering one on TAB would be a suggestion that produces a 201 and no content.

func CompleteCensusBlockTypes added in v0.3.0

func CompleteCensusBlockTypes(rt *Runtime) func(*cobra.Command, []string, string) ([]string, cobra.ShellCompDirective)

CompleteCensusBlockTypes completes the <blockType> argument of `pay blocks schema|example|new|add`: the entity named by --collection when it is given, otherwise every entity the cached census read.

func CompleteCensusFieldPaths added in v0.3.0

func CompleteCensusFieldPaths(rt *Runtime, entityArg bool, extra func(*cobra.Command, []string, string) ([]string, cobra.ShellCompDirective)) func(*cobra.Command, []string, string) ([]string, cobra.ShellCompDirective)

CompleteCensusFieldPaths completes a blocks-field --field for the catalog verbs and `pay describe`: the entity's declared blocks fields plus every pattern the census saw (`layout`, `layout[].blocks`) and the parent-scoped form (`group.blocks`). The entity is --collection when the command has one and it is set, else the first positional argument when entityArg says that argument IS an entity (`pay blocks types pages`, `pay describe pages`); otherwise (`pay blocks schema text`) every entity the census read. extra, when set, supplies the command's ordinary field paths as well (describe's --field takes any field).

func CompleteCollections

func CompleteCollections(rt *Runtime) func(*cobra.Command, []string, string) ([]string, cobra.ShellCompDirective)

CompleteCollections completes a collection slug from the cached index.

func CompleteEntities

func CompleteEntities(rt *Runtime) func(*cobra.Command, []string, string) ([]string, cobra.ShellCompDirective)

CompleteEntities completes a collection OR global slug, for `pay describe`.

func CompleteEntitiesVariadic added in v0.3.0

func CompleteEntitiesVariadic(rt *Runtime) func(*cobra.Command, []string, string) ([]string, cobra.ShellCompDirective)

CompleteEntitiesVariadic completes collection or global slugs for a command that takes several (`pay blocks learn pages ctas`), skipping those given.

func CompleteEntityFlag added in v0.3.0

func CompleteEntityFlag(rt *Runtime) func(*cobra.Command, []string, string) ([]string, cobra.ShellCompDirective)

CompleteEntityFlag completes a flag whose value is a collection or global slug (`--collection`), whatever positional arguments are already given.

func CompleteEnum

func CompleteEnum(values ...string) func(*cobra.Command, []string, string) ([]string, cobra.ShellCompDirective)

CompleteEnum completes a fixed value set, for --output and friends.

func CompleteFieldPaths

func CompleteFieldPaths(rt *Runtime, mode FieldMode) func(*cobra.Command, []string, string) ([]string, cobra.ShellCompDirective)

CompleteFieldPaths completes a field path for the collection already on the command line. It decodes at most the single shard for that collection (§9.9); a missing or generation-mismatched shard yields nothing.

func CompleteGlobals

func CompleteGlobals(rt *Runtime) func(*cobra.Command, []string, string) ([]string, cobra.ShellCompDirective)

CompleteGlobals completes a global slug from the cached index.

func CompleteProfiles

func CompleteProfiles(rt *Runtime) func(*cobra.Command, []string, string) ([]string, cobra.ShellCompDirective)

func Handle

func Handle(rt *Runtime, name string, h Handler) func(*cobra.Command, []string) error

Handle adapts a Handler to cobra's RunE. `name` is the envelope's `command` field and the audit log's command name; it is the space-joined command path without the "pay" prefix ("auth login", "find").

Handle is the ONLY place a command's output reaches a stream. A Handler that returns (nil, nil) is a programming error and surfaces as exit 1.

func Main

func Main() int

Main is the entry point cmd/pay/main.go calls. It returns the exit status instead of taking it, so nothing below cmd/ ever calls os.Exit.

func PathAdvice added in v0.3.0

func PathAdvice(exe string, pathEntries []string, home string) string

PathAdvice is the one remedy text for "the binary's directory is not on $PATH", shared by `pay doctor` and install.sh (which prints the same sentences). The robust fix is a link from a directory the shell ALREADY searches; editing rc files helps only the shells that read them.

func Register

func Register(f factory)

Register adds a subcommand factory to the root tree.

Every command file calls this from an init(), so root.go never has to name the individual commands and several agents can add commands to the same package without editing a shared switch. Registration order does not matter: the tree is sorted by command name before assembly, which makes `pay --help` and the alias-resolution order deterministic.

func Run

func Run(ctx context.Context, app App) (code int)

Run executes one PayCLI invocation and returns its exit status. It never panics out to the caller: a panic in a command is converted to exit 1 with an `internal` envelope, because an agent parsing stdout must always get an envelope.

func SetHelp

func SetHelp(cmd *cobra.Command, h *Help)

SetHelp attaches a Help model to a command.

func UpdateHint

func UpdateHint(statePath, currentVersion string) string

UpdateHint is the one-line notice `pay version` and `pay doctor` print when a newer release was recorded by an earlier --check. It never performs I/O beyond reading the state file, so it is safe on every command path.

func WhereOperatorAliases

func WhereOperatorAliases() []string

WhereOperatorAliases is the flat alias list §10.4 puts on the --where flag.

Types

type App

type App struct {
	// Args is os.Args[1:] — the program name is not included.
	Args []string
	// Env is os.Environ()'s "NAME=value" form.
	Env []string

	Stdin  io.Reader
	Stdout io.Writer
	Stderr io.Writer

	// Now is the only clock the program has. Tests pin it.
	Now func() time.Time

	// HTTP replaces the transport internal/payload would otherwise build. A
	// test points it at an httptest.Server; production leaves it nil.
	HTTP http.RoundTripper

	// Dirs overrides the §4.1 directory layout wholesale. A zero value is
	// derived from Env.
	Dirs config.Paths

	// WorkDir is the directory project discovery (§4.3) walks up from.
	WorkDir string

	// Terminal facts. False is the safe answer: PayCLI never changes output
	// shape based on a TTY (§10), it only uses these for the interactive
	// confirmation prompt (§12.2) and the "you typed a key on a terminal"
	// warning (§5.1 step 3).
	StdinIsTTY  bool
	StdoutIsTTY bool
	StderrIsTTY bool

	// NoSignals disables the SIGINT/SIGTERM handler. Tests set it; the
	// in-process handler would otherwise leak across `go test`.
	NoSignals bool

	// Executable is the path the running binary was started from, symlinks
	// NOT resolved (os.Executable). `pay doctor` checks that its directory is
	// on $PATH. Empty means unknown, and the check reports `unknown`.
	Executable string
}

App is the injected process surface. A zero value is unusable; Run substitutes inert defaults (io.Discard, a fixed clock) for anything left nil so that a malformed App can never panic mid-command.

type ArgSpec

type ArgSpec struct {
	Name       string   `json:"name"`
	Required   bool     `json:"required"`
	Type       string   `json:"type"`
	ValuesFrom string   `json:"values_from,omitempty"`
	Values     []string `json:"values,omitempty"`
	Example    string   `json:"example,omitempty"`
}

ArgSpec documents one positional argument (§10.4).

type BackupResult added in v0.3.0

type BackupResult struct {
	// Paths are the files written (or, for documents this invocation had
	// already backed up, the file written the first time).
	Paths []string
	// Skipped are the ids the backup read did not return.
	Skipped []any
	// Redacted are the values masked in the files, as "<doc>: <path>". They
	// are not in the backup, so a restore cannot bring them back.
	Redacted []string
}

BackupResult is what one backup pass produced.

type BackupTarget added in v0.3.0

type BackupTarget struct {
	Collection *collTarget
	Global     *globalTarget
	IDs        []any
	Params     query.Params
}

BackupTarget names the documents a write is about to change.

Exactly one of Collection and Global is set. IDs are the collection document ids; when a writeOp carries the target, nil IDs means "the ids the writeOp was given" (withIDs), which is how the bulk verbs hand over the ids §12.3 resolved. Params are the WRITE's query parameters: only Locale, FallbackLocale and Trash are consulted — the read always uses depth=0, and draft=true exactly when the entity has drafts.

type Check

type Check struct {
	Name   string `json:"name"`
	Status string `json:"status"`
	Detail string `json:"detail"`
	Hint   string `json:"hint,omitempty"`
	Value  any    `json:"value,omitempty"`
}

Check is one diagnostic line.

type CommandSpec

type CommandSpec struct {
	Path        []string   `json:"path"`
	Short       string     `json:"short"`
	Args        []ArgSpec  `json:"args"`
	Flags       []FlagSpec `json:"flags"`
	Subcommands []string   `json:"subcommands,omitempty"`
	Output      OutputSpec `json:"output"`
	ExitCodes   []int      `json:"exit_codes"`
	Examples    []Example  `json:"examples"`
	Mistakes    []Mistake  `json:"common_mistakes,omitempty"`
	SeeAlso     []string   `json:"see_also,omitempty"`
}

CommandSpec is §10.4's machine-readable help.

type Deps

type Deps struct {
	// RT is the shared runtime.
	RT *Runtime
	// Client is the configured Payload REST client.
	Client *payload.Client
	// Manifest is the discovery index, or nil when discovery could not answer.
	// A nil manifest disables every client-side rejection rather than inventing
	// one, which is §9.3's tri-state rule applied at the top.
	Manifest *discovery.Manifest
	// FetchURL downloads a remote upload source (§13). It is a field so unit
	// tests never reach the network.
	FetchURL func(ctx context.Context, rawurl string) (body io.ReadCloser, contentType string, size int64, err error)
	// contains filtered or unexported fields
}

Deps is one data command's resolved dependencies.

func (*Deps) BackupBeforeWrite added in v0.3.0

func (d *Deps) BackupBeforeWrite(ctx context.Context, command string, bt BackupTarget) (*BackupResult, error)

BackupBeforeWrite is the exported §12.8 hook: it backs up every document bt names and returns the files. With backups off it does nothing and returns an empty result. Any failure — the read or the file — is backup_failed (exit 1) with the --no-backup hint, and the caller MUST NOT send its write.

func (*Deps) BackupPreview added in v0.3.0

func (d *Deps) BackupPreview(command string, bt BackupTarget) *backupPreview

BackupPreview is would_backup for a dry run: the files the real run would write, without reading or writing anything. nil when backups are off.

func (*Deps) BackupsEnabled added in v0.3.0

func (d *Deps) BackupsEnabled() bool

BackupsEnabled reports whether a write in this invocation will be backed up. A caller that must do extra work only to name the documents (resolve ids for the passthrough delete, look up a version's parent) checks this first, so a user without backups never pays for it.

func (*Deps) ResolveDocBySlug added in v0.3.0

func (d *Deps) ResolveDocBySlug(ctx context.Context, t *collTarget, slug string, o SlugLookup) (*DocRef, error)

ResolveDocBySlug finds exactly one document of collection t whose slug field equals slug, in one bounded request (limit 2, id-only select):

  • no match -> doc_not_found (exit 4), with a hint that names --draft when the lookup did not use it (the slug may exist only in a draft);
  • several -> slug_ambiguous (exit 5), with the matching ids in error.did_you_mean;
  • exactly one -> its DocRef.

It validates the slug field against the collection's field shard when one is known (a Payload `where` on an unknown field is a 400 QueryError, or worse a silent match-all on some adapters), and never guesses a field that is not there. Callers pass the same --draft/--trash/--locale they will use for the follow-up read, so the id they get is the document they will then read.

type DiscoverOptions

type DiscoverOptions struct {
	Deep             bool
	AllowWriteProbes bool
	NoLabels         bool
	NoProbes         bool
}

DiscoverOptions are the knobs `pay discover` exposes. The zero value is what every other command uses.

type DocRef added in v0.3.0

type DocRef struct {
	// ID is the id exactly as Payload returned it (a JSON number on Postgres,
	// a string on MongoDB), for envelopes.
	ID any
	// IDString is the same id rendered for a URL path or a next.cmd.
	IDString string
	// Slug is the value that matched.
	Slug string
}

DocRef is the one document a slug resolved to.

type Example

type Example struct {
	Why string `json:"why"`
	Cmd string `json:"cmd"`
}

Example is one copy-pasteable invocation.

type FieldMode

type FieldMode string

FieldMode selects which field-path projection a completion offers.

const (
	// FieldQueryable completes --where / --or paths.
	FieldQueryable FieldMode = "queryable"
	// FieldSortable completes --sort.
	FieldSortable FieldMode = "sortable"
	// FieldSelectable completes --select / --select-exclude.
	FieldSelectable FieldMode = "selectable"
	// FieldDate completes --date-field.
	FieldDate FieldMode = "date"
)

type FlagInfo

type FlagInfo struct {
	Grammar    string   `json:"grammar,omitempty"`
	Operators  []string `json:"operators,omitempty"`
	Values     []string `json:"values,omitempty"`
	Repeatable bool     `json:"repeatable,omitempty"`
	Min        *int     `json:"min,omitempty"`
	Max        *int     `json:"max,omitempty"`
	// Note is printed in the FLAGS section, e.g. "no-op on this project:
	// localization is disabled".
	Note string `json:"note,omitempty"`
}

FlagInfo is the §10.4 detail for one flag.

type FlagSpec

type FlagSpec struct {
	Name       string   `json:"name"`
	Shorthand  string   `json:"shorthand,omitempty"`
	Type       string   `json:"type"`
	Repeatable bool     `json:"repeatable"`
	Default    any      `json:"default"`
	Usage      string   `json:"usage"`
	Grammar    string   `json:"grammar,omitempty"`
	Operators  []string `json:"operators,omitempty"`
	Values     []string `json:"values,omitempty"`
	Min        *int     `json:"min,omitempty"`
	Max        *int     `json:"max,omitempty"`
}

FlagSpec is one flag of a CommandSpec.

type Handler

type Handler func(ctx context.Context, rt *Runtime, args []string) (*output.Envelope, error)

Handler is the shape every PayCLI command implements. Returning an envelope and an error is deliberate: the envelope is rendered when err is nil, and the error is normalised into an error envelope otherwise, so no command has to know about exit codes, --path, --output or meta.

type Help

type Help struct {
	// Synopsis lines are printed verbatim under SYNOPSIS, metavariables and
	// all.
	Synopsis []string

	// Long is optional prose printed under the one-line Short.
	Long string

	// Discovered renders section 3 for this command. Returning nil falls back
	// to the shared collection inventory when Collections is true.
	Discovered func(rt *Runtime, m *discovery.Manifest) []string

	// Collections asks for the shared "collections in this project" block in
	// section 3.
	Collections bool
	// Globals asks for the globals inventory in section 3.
	Globals bool

	// Where and Sort switch on sections 4 and 5. They belong on any command
	// that accepts --where or --sort.
	Where bool
	Sort  bool

	// Args documents the positional arguments for §10.4.
	Args []ArgSpec
	// FlagInfo adds §10.4 detail (grammar, operators, bounds) that pflag
	// cannot express, keyed by flag name.
	FlagInfo map[string]FlagInfo

	Output    OutputSpec
	ExitCodes []int
	Examples  []Example
	Mistakes  []Mistake
	SeeAlso   []string

	// Notes are extra bullet lines printed after FLAGS. Use them for the
	// "this flag is a no-op on this project" callouts §10.5 item 6 requires.
	Notes []string
}

Help is the §10.5 model for one command's help text. Every command supplies the parts that cannot be derived from its cobra definition; the flag table, the command path and the subcommand list are read off cobra itself so the two can never drift.

A command with no Help still renders all eleven sections — it simply has no examples and no mistakes to show. That is a visible hole rather than a silent one, which is the point.

func HelpOf

func HelpOf(cmd *cobra.Command) *Help

HelpOf returns the Help model attached to a command, or an empty one.

type Mistake

type Mistake struct {
	Wrong string `json:"wrong"`
	Right string `json:"right"`
}

Mistake is one numbered anti-pattern and its correction. §10.5's hard rule: every "you cannot X" is followed by "do Y instead", which is why Right is not optional.

type OutputSpec

type OutputSpec struct {
	Kind      output.DataKind `json:"data_kind"`
	Paginated bool            `json:"paginated,omitempty"`
	Skeleton  string          `json:"skeleton,omitempty"`
}

OutputSpec is §10.4's output block.

type Runtime

type Runtime struct {
	App App

	// Env is the environment snapshot every layer reads from.
	Env config.Env
	// Paths is the resolved §4.1 layout.
	Paths config.Paths
	// Project is the detected Payload project (§4.3), never nil.
	Project *config.Project
	// UserFile and ProjectFile are the two config layers, never nil.
	UserFile    *config.File
	ProjectFile *config.File
	// Cfg is the resolved configuration. Nil until the persistent pre-run has
	// executed, which is why every command handler receives it already set.
	Cfg *config.Resolved

	// Command is the dotted command path of the command being run ("auth
	// login"), used for envelope.command and the audit log.
	Command string

	// Out renders envelopes. Commands must not write to App.Stdout directly.
	Out *output.Writer
	// Log is the structured logger; never nil.
	Log *slog.Logger

	// Flags is the parsed root flag state, exposed so a command can tell
	// "flag not given" from "flag given the default value".
	Flags *rootFlags
	// contains filtered or unexported fields
}

Runtime is the per-invocation world every command is handed. It owns the resolved configuration, the lazily built client, the cache session, the logger, the audit log and the renderer.

Everything expensive is lazy and memoised: `pay version` must work on a machine with no config, no network and no cache, so a Runtime that never resolves a credential never touches the keychain.

func (*Runtime) Audit

func (rt *Runtime) Audit() *audit.Logger

Audit returns the audit logger, building it on first use.

func (*Runtime) Cache

func (rt *Runtime) Cache() *cache.Store

Cache is the discovery cache store. It is permanently disabled (every read a miss, every write a no-op) under --no-cache.

func (*Runtime) CachedManifest

func (rt *Runtime) CachedManifest() (*discovery.Manifest, bool)

CachedManifest returns the discovery index from disk without any possibility of a network call. Help text (§10.5) and shell completion (§9.9) use this and nothing else: both must render instantly on a cold cache rather than block.

func (*Runtime) CachedShard

func (rt *Runtime) CachedShard(slug string, kind cache.EntityKind) (*discovery.Shard, bool)

CachedShard is the offline form used by completion and help, which may never trigger discovery.

func (*Runtime) Client

func (rt *Runtime) Client(ctx context.Context) (*payload.Client, error)

Client builds the Payload client for the resolved profile and credential.

It never hands out a client whose auth-collection slug is still §7.0's "auto" placeholder: in api-key mode the slug is part of the Authorization header, and a wrong slug answers HTTP 200 with the anonymous view rather than an error. resolveAuthCollection runs the §7.0 ladder (configured → cached → Stage -1) before the client escapes this function.

func (*Runtime) Confirmer

func (rt *Runtime) Confirmer() *safety.Confirmer

Confirmer builds §12.2's prompt over the injected streams.

func (*Runtime) Credential

func (rt *Runtime) Credential(ctx context.Context) (*secret.Credential, error)

Credential resolves §5.1's chain once per invocation.

func (*Runtime) Discovery

func (rt *Runtime) Discovery(ctx context.Context) (*discovery.Manifest, error)

Discovery returns the discovery index, running §7's pipeline when the cache cannot answer. It is memoised per invocation.

func (*Runtime) Elapsed

func (rt *Runtime) Elapsed() time.Duration

Elapsed is how long this invocation has been running.

func (*Runtime) Meta

func (rt *Runtime) Meta() output.Meta

Meta builds the §10.1 meta block from whatever the runtime currently knows.

func (*Runtime) NoRaw

func (rt *Runtime) NoRaw() bool

NoRaw reports whether --no-raw suppressed raw-body passthrough.

func (*Runtime) Now

func (rt *Runtime) Now() time.Time

Now is the injected clock. Nothing below internal/cli calls time.Now (§3.1).

func (*Runtime) PreviewSecret added in v0.3.0

func (rt *Runtime) PreviewSecret() (*secret.PreviewSecret, error)

PreviewSecret resolves F9's preview-secret chain once per invocation (PAY_PREVIEW_SECRET_<P>, PAY_PREVIEW_SECRET, the profile's preview_secret_env, credentials.json). A nil secret with a nil error means none is configured; whether that is fatal is the caller's call, because a preview_path without {secret} needs none.

Like Credential it re-arms the logger, so the literal is scrubbed from every later log line on top of the per-request URL scrubbing the payload client does.

func (*Runtime) RunDiscovery

func (rt *Runtime) RunDiscovery(ctx context.Context, opts DiscoverOptions) (*discovery.Manifest, error)

RunDiscovery executes §7's pipeline and persists the result (§8.7).

func (*Runtime) Scope

func (rt *Runtime) Scope() (cache.Scope, error)

Scope is the §8.1 cache scope for the resolved connection and credential.

func (*Runtime) SecretStore

func (rt *Runtime) SecretStore() *secret.Store

SecretStore is the credentials.json + keychain store for this profile set.

func (*Runtime) Secrets

func (rt *Runtime) Secrets() []string

Secrets returns the literal credential values that must be scrubbed from every log line and every rendered byte (§5.3). It never resolves a credential on its own.

func (*Runtime) Session

func (rt *Runtime) Session() *cache.Session

Session is the per-invocation cache session (§8.6).

func (*Runtime) SetDataBytes

func (rt *Runtime) SetDataBytes(n int64)

SetDataBytes makes meta.bytes report the size of the rendered payload rather than the bytes read from the network. `pay explain` is the case §18 names.

func (*Runtime) Shard

func (rt *Runtime) Shard(ctx context.Context, slug string, kind cache.EntityKind) (*discovery.Shard, bool)

Shard returns one entity's field schema, decoding it from the cache when the current invocation did not produce it.

func (*Runtime) Stderr

func (rt *Runtime) Stderr() io.Writer

Stderr is where human-facing notices and prompts go. Never the envelope.

func (*Runtime) Stdin

func (rt *Runtime) Stdin() io.Reader

Stdin is the command's input stream.

func (*Runtime) Warn

func (rt *Runtime) Warn(w ...output.Warning)

Warn records an envelope warning. Duplicates (same code and message) are collapsed so a fan-out cannot emit the same advice a hundred times.

func (*Runtime) Warnf

func (rt *Runtime) Warnf(code, format string, args ...any)

Warnf records a warning built from a code and a formatted message.

func (*Runtime) Warnings

func (rt *Runtime) Warnings() []output.Warning

Warnings returns the warnings recorded so far.

type SlugLookup added in v0.3.0

type SlugLookup struct {
	// Field is the field to match; "" means DefaultSlugField.
	Field string
	// Draft matches against each document's NEWEST draft (?draft=true). A
	// slug that was changed in an unpublished draft is found only this way;
	// without it the match runs against the stored (published, or
	// never-published) state, exactly like a bare `pay find`.
	Draft bool
	// Trash includes soft-deleted documents.
	Trash bool
	// Locale matches a localized slug in this locale ("" = the default).
	Locale string
}

SlugLookup says how ResolveDocBySlug searches.

Jump to

Keyboard shortcuts

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