props

package
v1.10.2 Latest Latest
Warning

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

Go to latest
Published: Apr 1, 2026 License: MIT Imports: 23 Imported by: 0

README

Props

The core dependency injection container for GTB applications.

Props holds global state including:

  • Tool metadata
  • Logger instance
  • Configuration container
  • Filesystem abstraction (Afero)
  • Version information

For detailed documentation on design rationale and usage patterns, see the Props Component Documentation.

Documentation

Overview

Package props defines the Props dependency container, the central type-safe dependency injection mechanism used throughout GTB.

Props is a concrete struct that aggregates tool metadata, logger, configuration, filesystem (afero.Fs), embedded assets, version info, and error handler into a single value threaded through commands and services. It replaces context.Context-based DI with compile-time type safety.

The package also provides the feature flag system via SetFeatures, Enable, and Disable functional options, controlling which built-in commands (update, init, docs, mcp) are registered at startup. Tool release source metadata for GitHub and GitLab backends is managed through ReleaseSource.

Index

Examples

Constants

View Source
const (
	UpdateCmd    = FeatureCmd("update")
	InitCmd      = FeatureCmd("init")
	McpCmd       = FeatureCmd("mcp")
	DocsCmd      = FeatureCmd("docs")
	AiCmd        = FeatureCmd("ai")
	DoctorCmd    = FeatureCmd("doctor")
	ConfigCmd    = FeatureCmd("config")
	ChangelogCmd = FeatureCmd("changelog")
)
View Source
const TelemetryCmd = FeatureCmd("telemetry")

TelemetryCmd is the feature flag for the telemetry command group. Default disabled — tool authors must explicitly enable it.

Variables

DefaultFeatures is the list of features enabled by default.

Functions

This section is empty.

Types

type AssetMap

type AssetMap map[string]fs.FS

AssetMap is a custom type for a map of filesystems.

type AssetProvider

type AssetProvider interface {
	GetAssets() Assets
}

AssetProvider provides access to embedded assets.

type Assets

type Assets interface {
	fs.FS
	fs.ReadDirFS
	fs.GlobFS
	fs.StatFS

	Slice() []fs.FS
	Names() []string
	Get(name string) fs.FS
	Register(name string, fs fs.FS)
	For(names ...string) Assets
	Merge(others ...Assets) Assets
	Exists(name string) (fs.FS, error)
	Mount(f fs.FS, prefix string)
}

Assets is an interface that wraps a map of fs.FS pointers and implements the standard fs interfaces.

func NewAssets

func NewAssets(assets ...AssetMap) Assets

NewAssets creates a new Assets wrapper with the given AssetMap pointers.

type ConfigProvider

type ConfigProvider interface {
	GetConfig() config.Containable
}

ConfigProvider provides access to the application configuration.

type CoreProvider

type CoreProvider interface {
	LoggerProvider
	ConfigProvider
	FileSystemProvider
}

CoreProvider provides the three most commonly needed capabilities.

type DeliveryMode added in v1.9.0

type DeliveryMode string

DeliveryMode controls the delivery guarantee for telemetry events.

const (
	// DeliveryAtLeastOnce deletes spill files after successful send.
	// Possible duplicates if the ack is lost; no data loss.
	DeliveryAtLeastOnce DeliveryMode = "at_least_once"
	// DeliveryAtMostOnce deletes spill files before sending.
	// Possible data loss; no duplicates.
	DeliveryAtMostOnce DeliveryMode = "at_most_once"
)

type ErrorHandlerProvider

type ErrorHandlerProvider interface {
	GetErrorHandler() errorhandling.ErrorHandler
}

ErrorHandlerProvider provides access to the error handler.

type EventType added in v1.9.0

type EventType string

EventType identifies the category of telemetry event. Defined here alongside TelemetryCollector so that commands can reference event type constants without importing pkg/telemetry. The same constants are mirrored in pkg/telemetry — since EventType is a string typedef, values from either package are interchangeable.

const (
	EventCommandInvocation EventType = "command.invocation"
	EventCommandError      EventType = "command.error"
	EventFeatureUsed       EventType = "feature.used"
	EventUpdateCheck       EventType = "update.check"
	EventUpdateApplied     EventType = "update.applied"
	EventDeletionRequest   EventType = "data.deletion_request"
)

type Feature

type Feature struct {
	Cmd     FeatureCmd `json:"cmd" yaml:"cmd"`
	Enabled bool       `json:"enabled" yaml:"enabled"`
}

Feature represents the state of a feature (Enabled/Disabled).

func SetFeatures

func SetFeatures(mutators ...FeatureState) []Feature

SetFeatures applies a series of mutators to the standard default set.

Example
package main

import (
	"fmt"

	"github.com/phpboyscout/go-tool-base/pkg/props"
)

func main() {
	features := props.SetFeatures(
		props.Disable(props.InitCmd),
		props.Enable(props.AiCmd),
		props.Enable(props.TelemetryCmd),
	)

	for _, f := range features {
		if f.Enabled {
			fmt.Println("enabled:", f.Cmd)
		}
	}
}

type FeatureCmd

type FeatureCmd string

FeatureCmd identifies a built-in feature that can be enabled or disabled.

type FeatureState

type FeatureState func([]Feature) []Feature

FeatureState is a functional option that mutates the list of features.

func Disable

func Disable(cmd FeatureCmd) FeatureState

Disable returns a FeatureState that disables the given command.

func Enable

func Enable(cmd FeatureCmd) FeatureState

Enable returns a FeatureState that enables the given command.

type FileSystemProvider

type FileSystemProvider interface {
	GetFS() afero.Fs
}

FileSystemProvider provides access to the application filesystem.

type LoggerProvider

type LoggerProvider interface {
	GetLogger() logger.Logger
}

LoggerProvider provides access to the application logger.

type LoggingConfigProvider

type LoggingConfigProvider interface {
	LoggerProvider
	ConfigProvider
}

LoggingConfigProvider is the most common combination — logging and configuration.

type Props

type Props struct {
	Tool         Tool
	Logger       logger.Logger
	Config       config.Containable
	Assets       Assets
	FS           afero.Fs
	Version      version.Version
	ErrorHandler errorhandling.ErrorHandler
	Collector    TelemetryCollector // always non-nil; noop when telemetry disabled
}

Props is the primary dependency injection container for GTB applications. When writing functions that accept Props, consider whether a narrow interface (LoggerProvider, ConfigProvider, etc.) would suffice.

func (*Props) GetAssets

func (p *Props) GetAssets() Assets

GetAssets returns the embedded assets.

func (*Props) GetConfig

func (p *Props) GetConfig() config.Containable

GetConfig returns the application configuration.

func (*Props) GetErrorHandler

func (p *Props) GetErrorHandler() errorhandling.ErrorHandler

GetErrorHandler returns the error handler.

func (*Props) GetFS

func (p *Props) GetFS() afero.Fs

GetFS returns the application filesystem.

func (*Props) GetLogger

func (p *Props) GetLogger() logger.Logger

GetLogger returns the application logger.

func (*Props) GetTool

func (p *Props) GetTool() Tool

GetTool returns the tool metadata.

func (*Props) GetVersion

func (p *Props) GetVersion() version.Version

GetVersion returns the version information.

type ReleaseSource

type ReleaseSource struct {
	Type    string `json:"type"    yaml:"type"`
	Host    string `json:"host"    yaml:"host"`
	Owner   string `json:"owner"   yaml:"owner"`
	Repo    string `json:"repo"    yaml:"repo"`
	Private bool   `json:"private" yaml:"private"`
	// Params holds provider-specific configuration key/value pairs.
	// Keys use snake_case. Valid keys are documented per provider.
	Params map[string]string `json:"params,omitempty" yaml:"params,omitempty"`
}

ReleaseSource identifies the platform and repository where the tool's releases are published. Used by the self-update system to check for and download new versions. Supported types: "github", "gitlab", "bitbucket", "gitea", "codeberg", "direct".

type TelemetryCollector added in v1.9.0

type TelemetryCollector interface {
	// Track records a telemetry event. No-op when the collector is disabled.
	Track(eventType EventType, name string, extra map[string]string)
	// TrackCommand records a command invocation with duration and exit code.
	TrackCommand(name string, durationMs int64, exitCode int, extra map[string]string)
	// TrackCommandExtended records a command invocation with full context including
	// arguments and error message. When ExtendedCollection is disabled on the
	// collector, args and errMsg are silently dropped — callers do not need to
	// check the flag themselves.
	TrackCommandExtended(name string, args []string, durationMs int64, exitCode int, errMsg string, extra map[string]string)
	// Flush sends all buffered events to the backend and clears the buffer.
	// Checks for and sends spill files before flushing the current buffer.
	Flush(ctx context.Context) error
	// BackendInfo returns a human-readable description of the active backend
	// (e.g. "otlp (otlp-gateway-prod-gb-south-1.grafana.net)", "noop", "file").
	BackendInfo() string
	// Close flushes pending events and shuts down the backend gracefully.
	// Must be called on process exit to ensure backends like OTLP flush
	// their internal batch queues.
	Close(ctx context.Context) error
	// Drop clears all buffered events and deletes any spill files without sending.
	Drop() error
}

TelemetryCollector is the interface through which commands emit telemetry events. Defined here (not in pkg/telemetry) to avoid an import cycle. The concrete implementation is *telemetry.Collector from pkg/telemetry. Props.Collector is always non-nil — when telemetry is disabled it is a noop.

type TelemetryConfig added in v1.9.0

type TelemetryConfig struct {
	// Endpoint is the HTTP JSON endpoint to POST events to.
	// Ignored when OTelEndpoint is set or when Backend is non-nil.
	Endpoint string `json:"endpoint,omitempty" yaml:"endpoint,omitempty"`

	// OTelEndpoint is the OTLP/HTTP base URL (e.g. "https://collector:4318").
	// Takes precedence over Endpoint when set.
	OTelEndpoint string `json:"otel_endpoint,omitempty" yaml:"otel_endpoint,omitempty"`

	// OTelHeaders are HTTP headers sent with every OTLP request (e.g. auth tokens).
	OTelHeaders map[string]string `json:"otel_headers,omitempty" yaml:"otel_headers,omitempty"`

	// OTelInsecure disables TLS for the OTLP endpoint — use only for local collectors.
	OTelInsecure bool `json:"otel_insecure,omitempty" yaml:"otel_insecure,omitempty"`

	// Backend is an optional factory for a custom telemetry backend.
	// Typed as func(*Props) any to avoid importing pkg/telemetry from pkg/props.
	// The returned value must implement telemetry.Backend — pkg/cmd/root performs
	// the type assertion. Takes precedence over Endpoint and OTelEndpoint when set.
	// Not serialisable — set programmatically in tool setup.
	Backend func(*Props) any `json:"-" yaml:"-"`

	// DeletionRequestor is an optional factory for a custom GDPR deletion requestor.
	// Typed as func(*Props) any to avoid importing pkg/telemetry from pkg/props.
	// The returned value must implement telemetry.DeletionRequestor — pkg/cmd/root
	// performs the type assertion. If nil, falls back to sending a
	// data.deletion_request event through the existing backend.
	// Not serialisable — set programmatically in tool setup.
	DeletionRequestor func(*Props) any `json:"-" yaml:"-"`

	// ForceEnabled bypasses the user consent prompt and enables telemetry
	// unconditionally. The telemetry enable/disable/reset commands remain
	// functional so users can still inspect status, but collection cannot be
	// turned off. Intended for enterprise tools deployed in controlled
	// environments where telemetry is a contractual requirement.
	// When set, the first-run consent prompt is suppressed.
	ForceEnabled bool `json:"force_enabled,omitempty" yaml:"force_enabled,omitempty"`

	// ExtendedCollection enables collection of command arguments and error messages
	// in telemetry events. Default: false. When false, args and errors are never
	// recorded regardless of what callers pass to TrackCommandExtended.
	//
	// Enable this only in closed enterprise environments where users are
	// contractually bound by security policies. In public-facing tools, leave
	// this disabled to preserve user privacy.
	ExtendedCollection bool `json:"extended_collection,omitempty" yaml:"extended_collection,omitempty"`

	// DeliveryMode controls the delivery guarantee. Default: DeliveryAtLeastOnce.
	DeliveryMode DeliveryMode `json:"delivery_mode,omitempty" yaml:"delivery_mode,omitempty"`

	// Metadata is additional key/value pairs included in every event.
	// Useful for custom dimensions like environment name or deployment tier.
	Metadata map[string]string `json:"metadata,omitempty" yaml:"metadata,omitempty"`
}

TelemetryConfig holds tool-author telemetry declarations. It is embedded in Tool and specifies where and how to send telemetry. The end-user's opt-in state is stored in the config file under telemetry.enabled and telemetry.local_only — endpoints are not user-configurable.

type Tool

type Tool struct {
	Name        string                   `json:"name" yaml:"name"`
	Summary     string                   `json:"summary" yaml:"summary"`
	Description string                   `json:"description" yaml:"description"`
	Features    []Feature                `json:"features" yaml:"features"`
	Help        errorhandling.HelpConfig `json:"-" yaml:"-"`

	// ReleaseSource is the source of truth for the tool's releases (GitHub or GitLab)
	ReleaseSource ReleaseSource `json:"release_source" yaml:"release_source"`

	// Telemetry holds tool-author telemetry configuration.
	// Zero-value is safe — tools that don't set it are unaffected.
	Telemetry TelemetryConfig `json:"telemetry" yaml:"telemetry"`
}

Tool holds metadata about the CLI tool: its identity, feature flags, release source for self-updates, help channel configuration, and telemetry settings. It is embedded in Props and passed to all commands.

func (Tool) GetReleaseSource

func (t Tool) GetReleaseSource() (sourceType, owner, repo string)

GetReleaseSource returns the release source type, owner, and repo.

func (Tool) IsDisabled

func (t Tool) IsDisabled(cmd FeatureCmd) bool

IsDisabled checks if a feature is disabled.

func (Tool) IsEnabled

func (t Tool) IsEnabled(cmd FeatureCmd) bool

IsEnabled checks if a feature is enabled. It checks the Features slice first, falling back to built-in defaults.

Example
package main

import (
	"fmt"

	"github.com/phpboyscout/go-tool-base/pkg/props"
)

func main() {
	tool := props.Tool{
		Name: "mytool",
		Features: props.SetFeatures(
			props.Enable(props.AiCmd),
		),
	}

	fmt.Println("AI:", tool.IsEnabled(props.AiCmd))
	fmt.Println("Init:", tool.IsEnabled(props.InitCmd))
}
Output:
AI: true
Init: true

type ToolMetadataProvider

type ToolMetadataProvider interface {
	GetTool() Tool
}

ToolMetadataProvider provides access to tool configuration and metadata.

type VersionProvider

type VersionProvider interface {
	GetVersion() version.Version
}

VersionProvider provides access to version information.

Jump to

Keyboard shortcuts

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