Documentation
¶
Overview ¶
Package output renders catalog.Row values into the spec §4 JSON envelope.
The full envelope always carries the same keys (null when absent); preset trimming is applied by stripping keys before encoding. The rendering path is allocation-conscious but not micro-optimized — the hot path in M1 is the single-row lookup, not streaming output.
Index ¶
- Variables
- func ApplyFields(doc map[string]any, expr string) map[string]any
- func ApplyJQ(doc any, expr string) (any, error)
- func EmitDryRun(w io.Writer, p DryRunPlan) error
- func EmitEstimate(w io.Writer, r estimate.Result, opts Options) error
- func Encode(doc any, format string, pretty bool) ([]byte, error)
- func EncodeEnvelope(w io.Writer, env Envelope, pretty bool) error
- func Log(w io.Writer, event string, fields map[string]any)
- func Pipeline(r catalog.Row, opts Options) ([]byte, error)
- func ShouldColorize(w io.Writer, opts Options) bool
- type DryRunPlan
- type Envelope
- type EstimateEnvelope
- type EstimateItem
- type EstimateMonthlyTotal
- type Health
- type Location
- type Options
- type Preset
- type Price
- type Resource
- type Source
- type Terms
Constants ¶
This section is empty.
Variables ¶
var ErrDropped = errors.New("output: row dropped by preset filter")
ErrDropped signals that Pipeline intentionally emitted nothing — e.g. an aggregated row with IncludeAggregated=false. Callers should skip the row without treating this as a fatal error.
Functions ¶
func ApplyFields ¶
ApplyFields projects doc down to the requested comma-separated dot paths. Paths are split on `.`; numeric segments index into `[]any`. Missing paths are silently dropped. When multiple paths share a prefix they merge into the same parent. An empty expression returns doc unchanged.
func ApplyJQ ¶
ApplyJQ runs a gojq expression against doc. Zero iterator outputs return nil; one returns that value directly; multiple return a `[]any` of all results. Parse/runtime errors are wrapped with a "jq:" prefix.
func EmitDryRun ¶
func EmitDryRun(w io.Writer, p DryRunPlan) error
EmitDryRun writes the stable dry-run envelope to w.
func EmitEstimate ¶
EmitEstimate writes the result as JSON/YAML/TOML per Options.Format. For TOML, the envelope is re-wrapped as { "rows": items, ... } per the repo TOML convention (CLAUDE.md "TOML quirks").
func Encode ¶
Encode serializes doc to the requested format.
- "json" / "": compact by default, indented when pretty. Always terminated with a single newline.
- "yaml": yaml.v3 marshal; pretty is a no-op (yaml is always formatted). yaml.v3 already emits a trailing newline so we do not add another.
- "toml": go-toml/v2. TOML cannot represent a top-level array, so any slice-typed doc is wrapped as {"rows": doc} before marshaling.
Unknown formats return an error.
func EncodeEnvelope ¶
EncodeEnvelope writes the envelope as JSON to w. When pretty is false the encoding is compact (json.Encoder defaults); when true it's indented with two spaces. Always writes a trailing newline. Retained for M1 callers until Task 10 migrates them to Pipeline.
func Log ¶
Log emits one JSON object per call to w with a ts/event header. Intended for --verbose stderr tracing; errors marshaling are swallowed because verbose output is best-effort.
func Pipeline ¶
Pipeline is the single entry point used by every data-path command. It preset-projects, applies --fields, applies --jq, and encodes in one call. Callers writing multiple rows call Pipeline once per row so JSON output streams as NDJSON.
func ShouldColorize ¶
ShouldColorize reports whether human-facing output emitted to w may include ANSI color. It returns false when the caller set --no-color (consumed into Options.NoColor upstream from NO_COLOR / SKU_NO_COLOR), when w is not an *os.File, or when the underlying file descriptor is not a TTY. Data-format output paths never call this — agents always receive uncolored bytes.
Types ¶
type DryRunPlan ¶
type DryRunPlan struct {
Command string `json:"command"`
ResolvedArgs map[string]any `json:"resolved_args"`
Shards []string `json:"shards"`
TermsHash string `json:"terms_hash,omitempty"`
SQL string `json:"sql,omitempty"`
Preset string `json:"preset"`
}
DryRunPlan carries the resolved query plan emitted by commands when --dry-run is set. The rendered JSON follows spec §4 "Dry-run output".
type Envelope ¶
type Envelope struct {
Provider string `json:"provider,omitempty"`
Service string `json:"service,omitempty"`
SKUID string `json:"sku_id,omitempty"`
Resource *Resource `json:"resource,omitempty"`
Location *Location `json:"location,omitempty"`
Price []Price `json:"price,omitempty"`
Terms *Terms `json:"terms,omitempty"`
Health *Health `json:"health,omitempty"`
Source *Source `json:"source,omitempty"`
Raw any `json:"raw,omitempty"`
}
Envelope is the top-level §4 output object. Field ordering is enforced by the struct layout; json.Encoder writes keys in declaration order.
type EstimateEnvelope ¶
type EstimateEnvelope struct {
Items []EstimateItem `json:"items" yaml:"items" toml:"-"`
MonthlyTotal EstimateMonthlyTotal `json:"monthly_total" yaml:"monthly_total" toml:"monthly_total"`
}
EstimateEnvelope is the §4 shape for `sku estimate`.
type EstimateItem ¶
type EstimateItem struct {
Item string `json:"item" yaml:"item" toml:"item"`
Kind string `json:"kind" yaml:"kind" toml:"kind"`
SKUID string `json:"sku_id,omitempty" yaml:"sku_id,omitempty" toml:"sku_id,omitempty"`
Provider string `json:"provider" yaml:"provider" toml:"provider"`
Service string `json:"service" yaml:"service" toml:"service"`
Resource string `json:"resource" yaml:"resource" toml:"resource"`
Region string `json:"region,omitempty" yaml:"region,omitempty" toml:"region,omitempty"`
HourlyUSD float64 `json:"hourly_usd,omitempty" yaml:"hourly_usd,omitempty" toml:"hourly_usd,omitempty"`
Quantity float64 `json:"quantity,omitempty" yaml:"quantity,omitempty" toml:"quantity,omitempty"`
QuantityUnit string `json:"quantity_unit,omitempty" yaml:"quantity_unit,omitempty" toml:"quantity_unit,omitempty"`
MonthlyUSD float64 `json:"monthly_usd" yaml:"monthly_usd" toml:"monthly_usd"`
}
EstimateItem is one line-item in the output envelope.
type EstimateMonthlyTotal ¶
type EstimateMonthlyTotal struct {
Amount float64 `json:"amount" yaml:"amount" toml:"amount"`
Currency string `json:"currency" yaml:"currency" toml:"currency"`
}
EstimateMonthlyTotal is the monthly-total block carried in the envelope.
type Health ¶
type Health struct {
Uptime30d *float64 `json:"uptime_30d,omitempty"`
LatencyP50Ms *int64 `json:"latency_p50_ms,omitempty"`
LatencyP95Ms *int64 `json:"latency_p95_ms,omitempty"`
ThroughputTokensPerSec *float64 `json:"throughput_tokens_per_sec,omitempty"`
ObservedAt *int64 `json:"observed_at,omitempty"`
}
Health is the §4 health block (LLM-populated).
type Location ¶
type Location struct {
ProviderRegion *string `json:"provider_region"`
NormalizedRegion *string `json:"normalized_region"`
AvailabilityZone *string `json:"availability_zone"`
}
Location is the §4 location block.
type Options ¶
type Options struct {
Preset Preset
Format string
Pretty bool
Fields string
JQ string
IncludeRaw bool
IncludeAggregated bool
NoColor bool
}
Options configures the output Pipeline. Zero values are filled by WithDefaults: empty Preset becomes PresetAgent, empty Format becomes "json".
func (Options) WithDefaults ¶
WithDefaults returns a copy of o with zero fields filled in.
type Preset ¶
type Preset string
Preset enumerates the output-shape presets. Agent and Full are fully implemented in M1; Price and Compare get kind-aware projections in M2.
type Price ¶
type Price struct {
Amount float64 `json:"amount"`
Currency string `json:"currency"`
Unit string `json:"unit"`
Dimension string `json:"dimension"`
Tier *string `json:"tier"`
}
Price is a single price dimension as emitted in the output.
type Resource ¶
type Resource struct {
Kind string `json:"kind,omitempty"`
Name string `json:"name,omitempty"`
VCPU *int64 `json:"vcpu,omitempty"`
MemoryGB *float64 `json:"memory_gb,omitempty"`
StorageGB *float64 `json:"storage_gb,omitempty"`
GPUCount *int64 `json:"gpu_count,omitempty"`
ContextLength *int64 `json:"context_length,omitempty"`
MaxOutputTokens *int64 `json:"max_output_tokens,omitempty"`
Capabilities []string `json:"capabilities,omitempty"`
DurabilityNines *int64 `json:"durability_nines,omitempty"`
AvailabilityTier *string `json:"availability_tier,omitempty"`
Attributes map[string]any `json:"attributes,omitempty"`
}
Resource is the §4 resource block.
type Source ¶
type Source struct {
CatalogVersion string `json:"catalog_version"`
FetchedAt string `json:"fetched_at,omitempty"`
UpstreamID string `json:"upstream_id,omitempty"`
Freshness string `json:"freshness,omitempty"`
}
Source is the §4 source block.
type Terms ¶
type Terms struct {
Commitment string `json:"commitment"`
Tenancy *string `json:"tenancy,omitempty"`
OS *string `json:"os,omitempty"`
SupportTier *string `json:"support_tier,omitempty"`
Upfront *string `json:"upfront,omitempty"`
PaymentOption *string `json:"payment_option,omitempty"`
}
Terms is the §4 terms block. Empty-string sentinels become nil pointers.