Files
ConfigKit/records.go

236 lines
6.9 KiB
Go

package configkit
// Layer identifies the precedence layer responsible for a configuration value.
type Layer string
const (
LayerDefault Layer = "default"
LayerBase Layer = "base"
LayerProfile Layer = "profile"
LayerCLI Layer = "cli"
LayerResolution Layer = "resolution"
)
// ChangeKind identifies an application resolution operation. The zero value is
// used for input and default origins.
type ChangeKind string
const (
ChangeDerivedDefault ChangeKind = "derived_default"
ChangeNormalization ChangeKind = "normalization"
)
// Severity classifies a diagnostic.
type Severity string
const (
SeverityError Severity = "error"
SeverityWarning Severity = "warning"
)
// Code is a stable, machine-readable diagnostic classification.
type Code string
const (
CodeSourceInvalid Code = "source.invalid"
CodeSourceMissing Code = "source.missing"
CodeSourcePermission Code = "source.permission"
CodeSourceRead Code = "source.read"
CodeSourceNotRegular Code = "source.not_regular"
CodeSourceLimitExceeded Code = "source.limit_exceeded"
CodeSourceReaderUsed Code = "source.reader_used"
CodeYAMLInvalid Code = "yaml.invalid"
CodeYAMLEmpty Code = "yaml.empty"
CodeYAMLMultipleDocuments Code = "yaml.multiple_documents"
CodeYAMLRootType Code = "yaml.root_type"
CodeYAMLDuplicateKey Code = "yaml.duplicate_key"
CodeYAMLTag Code = "yaml.tag"
CodeYAMLAnchor Code = "yaml.anchor"
CodeYAMLAlias Code = "yaml.alias"
CodeYAMLMergeKey Code = "yaml.merge_key"
CodeYAMLScalar Code = "yaml.scalar"
CodeYAMLDepthLimit Code = "yaml.depth_limit"
CodeYAMLNodeLimit Code = "yaml.node_limit"
CodeSchemaRoot Code = "schema.root"
CodeSchemaUnsupportedType Code = "schema.unsupported_type"
CodeSchemaAmbiguousField Code = "schema.ambiguous_field"
CodeSchemaTag Code = "schema.tag"
CodeSchemaTextCodec Code = "schema.text_codec"
CodeSchemaInline Code = "schema.inline"
CodeSchemaCycle Code = "schema.cycle"
CodeSchemaProjectionLimit Code = "schema.projection_limit"
CodeSchemaCodec Code = "schema.codec"
CodeSchemaNonFinite Code = "schema.non_finite"
CodeSchemaDynamicType Code = "schema.dynamic_type"
CodeDecodeType Code = "decode.type"
CodeDecodeNull Code = "decode.null"
CodeDecodeRange Code = "decode.range"
CodeDecodeDuration Code = "decode.duration"
CodeDecodeText Code = "decode.text"
CodeDecodeUnknownField Code = "decode.unknown_field"
CodeDecodeArrayLength Code = "decode.array_length"
CodeOptionsInvalid Code = "options.invalid"
CodeOptionsUnavailable Code = "options.unavailable"
CodeImportDisabled Code = "import.disabled"
CodeVersionType Code = "version.type"
CodeVersionError Code = "version.error"
CodeVersionWarning Code = "version.warning"
CodeVersionHookFailed Code = "version.hook_failed"
CodeResolveError Code = "resolve.error"
CodeResolveWarning Code = "resolve.warning"
CodeResolveHookFailed Code = "resolve.hook_failed"
CodeResolveInvalidPath Code = "resolve.invalid_path"
CodeResolveInvalidKind Code = "resolve.invalid_kind"
CodeResolveInvalidRecord Code = "resolve.invalid_record"
CodeResolveInvalidTarget Code = "resolve.invalid_target"
CodeResolveInvalidValue Code = "resolve.invalid_value"
CodeResolveUnrecordedChange Code = "resolve.unrecorded_change"
CodeValidateError Code = "validate.error"
CodeValidateWarning Code = "validate.warning"
CodeValidateInvalidPath Code = "validate.invalid_path"
CodeValidateMutation Code = "validate.mutation"
)
// Location identifies a position in a configuration source. Zero line and column
// values mean that coordinates are unavailable or synthetic.
type Location struct {
SourceID string
Line int
Column int
}
// SourceInfo describes a source discovered during a load. Path is a canonical
// local path when one exists. ImportedFrom identifies the declaration that
// included this source.
type SourceInfo struct {
ID string
Label string
Path string
Layer Layer
ImportedFrom *Location
}
// Diagnostic is a safe structured problem report. Message and source labels must
// never contain configuration values or other secrets.
type Diagnostic struct {
Code Code
Severity Severity
Path Path
Message string
Primary *Location
Related []Location
}
// Origin describes where an effective definition came from. Multiple locations
// represent a composite origin.
type Origin struct {
Layer Layer
Locations []Location
Operation ChangeKind
}
// FieldInfo describes an effective configuration path.
type FieldInfo struct {
Explicit bool
Null bool
Origin Origin
}
// Change describes a definition or application-resolution operation. Historical
// values are intentionally not exposed by this record.
type Change struct {
Path Path
Origin Origin
Previous []Origin
Reasons []string
Dependencies []Path
}
func cloneLocation(location *Location) *Location {
if location == nil {
return nil
}
cloned := *location
return &cloned
}
func cloneLocations(locations []Location) []Location {
if locations == nil {
return nil
}
return append([]Location(nil), locations...)
}
func cloneSourceInfo(source SourceInfo) SourceInfo {
source.ImportedFrom = cloneLocation(source.ImportedFrom)
return source
}
func cloneSourceInfos(sources []SourceInfo) []SourceInfo {
if sources == nil {
return nil
}
cloned := make([]SourceInfo, len(sources))
for i, source := range sources {
cloned[i] = cloneSourceInfo(source)
}
return cloned
}
func cloneOrigin(origin Origin) Origin {
origin.Locations = cloneLocations(origin.Locations)
return origin
}
func cloneFieldInfo(info FieldInfo) FieldInfo {
info.Origin = cloneOrigin(info.Origin)
return info
}
func cloneChange(change Change) Change {
change.Path = change.Path.clone()
change.Origin = cloneOrigin(change.Origin)
if change.Previous != nil {
previous := make([]Origin, len(change.Previous))
for i, origin := range change.Previous {
previous[i] = cloneOrigin(origin)
}
change.Previous = previous
}
change.Reasons = append([]string(nil), change.Reasons...)
if change.Dependencies != nil {
dependencies := make([]Path, len(change.Dependencies))
for i, path := range change.Dependencies {
dependencies[i] = path.clone()
}
change.Dependencies = dependencies
}
return change
}
func cloneDiagnostic(diagnostic Diagnostic) Diagnostic {
diagnostic.Path = diagnostic.Path.clone()
diagnostic.Primary = cloneLocation(diagnostic.Primary)
diagnostic.Related = cloneLocations(diagnostic.Related)
return diagnostic
}
func cloneDiagnostics(diagnostics []Diagnostic) []Diagnostic {
if diagnostics == nil {
return nil
}
cloned := make([]Diagnostic, len(diagnostics))
for i, diagnostic := range diagnostics {
cloned[i] = cloneDiagnostic(diagnostic)
}
return cloned
}