package dorks import "fmt" // Registry is the in-memory store of loaded dork definitions. It is built // once at startup (via NewRegistry) and is safe for concurrent reads. type Registry struct { dorks []Dork byID map[string]int bySource map[string][]int byCategory map[string][]int } // NewRegistry loads every embedded dork YAML file, validates them, and // returns a ready-to-query Registry. An empty definitions tree is tolerated // and yields an empty (but non-nil) Registry. func NewRegistry() (*Registry, error) { ds, err := loadDorks() if err != nil { return nil, fmt.Errorf("loading dorks: %w", err) } return NewRegistryFromDorks(ds), nil } // NewRegistryFromDorks builds a Registry from an explicit slice of dorks // without touching the embedded filesystem. Intended for tests. func NewRegistryFromDorks(ds []Dork) *Registry { r := &Registry{ dorks: make([]Dork, len(ds)), byID: make(map[string]int, len(ds)), bySource: make(map[string][]int), byCategory: make(map[string][]int), } copy(r.dorks, ds) for i, d := range r.dorks { r.byID[d.ID] = i r.bySource[d.Source] = append(r.bySource[d.Source], i) r.byCategory[d.Category] = append(r.byCategory[d.Category], i) } return r } // List returns all loaded dorks. The returned slice must not be mutated. func (r *Registry) List() []Dork { return r.dorks } // Get returns the dork with the given id and a boolean indicating whether it // was found. func (r *Registry) Get(id string) (Dork, bool) { idx, ok := r.byID[id] if !ok { return Dork{}, false } return r.dorks[idx], true } // ListBySource returns every dork declared for the given source. func (r *Registry) ListBySource(source string) []Dork { idxs := r.bySource[source] out := make([]Dork, 0, len(idxs)) for _, i := range idxs { out = append(out, r.dorks[i]) } return out } // ListByCategory returns every dork tagged with the given category. func (r *Registry) ListByCategory(category string) []Dork { idxs := r.byCategory[category] out := make([]Dork, 0, len(idxs)) for _, i := range idxs { out = append(out, r.dorks[i]) } return out } // Stats returns aggregate counts grouped by source and category. func (r *Registry) Stats() Stats { s := Stats{ Total: len(r.dorks), BySource: make(map[string]int, len(r.bySource)), ByCategory: make(map[string]int, len(r.byCategory)), } for src, idxs := range r.bySource { s.BySource[src] = len(idxs) } for cat, idxs := range r.byCategory { s.ByCategory[cat] = len(idxs) } return s }