feat(provider): expose registry spec files

Add stable registry helpers for enumerating provider OpenAPI spec files, plus iterator coverage. This gives discovery consumers a direct way to aggregate provider docs without changing routing behaviour.

Co-Authored-By: Virgil <virgil@lethean.io>
This commit is contained in:
Virgil 2026-04-01 14:38:45 +00:00
parent 90e237ae31
commit b58de8f8f0
2 changed files with 60 additions and 0 deletions

View file

@ -152,3 +152,32 @@ func (r *Registry) Info() []ProviderInfo {
}
return infos
}
// SpecFiles returns all non-empty provider OpenAPI spec file paths.
// The result is deduplicated and sorted for stable discovery output.
func (r *Registry) SpecFiles() []string {
r.mu.RLock()
defer r.mu.RUnlock()
files := make(map[string]struct{}, len(r.providers))
for _, p := range r.providers {
if sf, ok := p.(interface{ SpecFile() string }); ok {
if path := sf.SpecFile(); path != "" {
files[path] = struct{}{}
}
}
}
out := make([]string, 0, len(files))
for path := range files {
out = append(out, path)
}
slices.Sort(out)
return out
}
// SpecFilesIter returns an iterator over all non-empty provider OpenAPI spec files.
func (r *Registry) SpecFilesIter() iter.Seq[string] {
return slices.Values(r.SpecFiles())
}

View file

@ -38,6 +38,13 @@ func (r *renderableProvider) Element() provider.ElementSpec {
return provider.ElementSpec{Tag: "core-stub-panel", Source: "/assets/stub.js"}
}
type specFileProvider struct {
stubProvider
specFile string
}
func (s *specFileProvider) SpecFile() string { return s.specFile }
type fullProvider struct {
streamableProvider
}
@ -177,3 +184,27 @@ func TestRegistry_Iter_Good(t *testing.T) {
}
assert.Equal(t, 2, count)
}
func TestRegistry_SpecFiles_Good(t *testing.T) {
reg := provider.NewRegistry()
reg.Add(&stubProvider{})
reg.Add(&specFileProvider{specFile: "/tmp/b.json"})
reg.Add(&specFileProvider{specFile: "/tmp/a.yaml"})
reg.Add(&specFileProvider{specFile: "/tmp/a.yaml"})
reg.Add(&specFileProvider{specFile: ""})
assert.Equal(t, []string{"/tmp/a.yaml", "/tmp/b.json"}, reg.SpecFiles())
}
func TestRegistry_SpecFilesIter_Good(t *testing.T) {
reg := provider.NewRegistry()
reg.Add(&specFileProvider{specFile: "/tmp/z.json"})
reg.Add(&specFileProvider{specFile: "/tmp/x.json"})
var files []string
for file := range reg.SpecFilesIter() {
files = append(files, file)
}
assert.Equal(t, []string{"/tmp/x.json", "/tmp/z.json"}, files)
}