// Package templates provides the built-in provider env-key skeletons shipped // inside the cc-switch binary. The data is embedded at compile time from // templates.yaml; no network or external file I/O is ever performed. // // Templates intentionally do NOT include secrets — only key names, hints, and // occasional defaults (e.g. a provider's canonical base URL). package templates import ( _ "embed" "fmt" "sort" "gopkg.in/yaml.v3" ) // Template describes one provider env skeleton. type Template struct { Name string `yaml:"name"` Description string `yaml:"description"` Env []EnvKey `yaml:"env"` } // EnvKey is one env entry inside a template. type EnvKey struct { Name string `yaml:"name"` Hint string `yaml:"hint,omitempty"` Default string `yaml:"default,omitempty"` } //go:embed templates.yaml var embeddedYAML []byte type fileShape struct { Templates []Template `yaml:"templates"` } // Parse parses the given YAML bytes into a slice of Templates. Exposed for // testing. func Parse(data []byte) ([]Template, error) { var f fileShape if err := yaml.Unmarshal(data, &f); err != nil { return nil, fmt.Errorf("parse templates: %w", err) } for i, t := range f.Templates { if t.Name == "" { return nil, fmt.Errorf("template[%d]: empty name", i) } if len(t.Env) == 0 { return nil, fmt.Errorf("template %q: env must have at least one key", t.Name) } for j, e := range t.Env { if e.Name == "" { return nil, fmt.Errorf("template %q env[%d]: empty key name", t.Name, j) } } } return f.Templates, nil } var cache []Template // All returns every embedded template. The result is cached; callers MUST NOT // mutate the returned slice (treat as read-only). func All() []Template { if cache != nil { return cache } ts, err := Parse(embeddedYAML) if err != nil { // Embedded data is authored in-repo; a parse failure here is a // programmer bug caught by tests, not a runtime condition. panic(fmt.Sprintf("embedded templates.yaml is invalid: %v", err)) } cache = ts return cache } // Get returns the template with the given name. func Get(name string) (Template, bool) { for _, t := range All() { if t.Name == name { return t, true } } return Template{}, false } // Names returns a sorted list of available template names. func Names() []string { all := All() names := make([]string, len(all)) for i, t := range all { names[i] = t.Name } sort.Strings(names) return names }