registry.go raw
1 //go:build !(js && wasm)
2
3 package database
4
5 import (
6 "context"
7 "sort"
8 "sync"
9
10 "next.orly.dev/pkg/lol/errorf"
11 )
12
13 // DriverFactory is the signature for database driver factory functions.
14 type DriverFactory func(ctx context.Context, cancel context.CancelFunc, cfg *DatabaseConfig) (Database, error)
15
16 // DriverInfo contains metadata about a registered driver.
17 type DriverInfo struct {
18 Name string
19 Description string
20 Factory DriverFactory
21 }
22
23 var (
24 driversMu sync.RWMutex
25 drivers = make(map[string]*DriverInfo)
26 )
27
28 // RegisterDriver registers a database driver with the given name and factory.
29 // This is typically called from init() in the driver package.
30 func RegisterDriver(name, description string, factory DriverFactory) {
31 driversMu.Lock()
32 defer driversMu.Unlock()
33 drivers[name] = &DriverInfo{
34 Name: name,
35 Description: description,
36 Factory: factory,
37 }
38 }
39
40 // GetDriver returns the factory for the named driver, or nil if not found.
41 func GetDriver(name string) DriverFactory {
42 driversMu.RLock()
43 defer driversMu.RUnlock()
44 if info, ok := drivers[name]; ok {
45 return info.Factory
46 }
47 return nil
48 }
49
50 // HasDriver returns true if the named driver is registered.
51 func HasDriver(name string) bool {
52 driversMu.RLock()
53 defer driversMu.RUnlock()
54 _, ok := drivers[name]
55 return ok
56 }
57
58 // ListDrivers returns a sorted list of registered driver names.
59 func ListDrivers() []string {
60 driversMu.RLock()
61 defer driversMu.RUnlock()
62 names := make([]string, 0, len(drivers))
63 for name := range drivers {
64 names = append(names, name)
65 }
66 sort.Strings(names)
67 return names
68 }
69
70 // ListDriversWithInfo returns information about all registered drivers.
71 func ListDriversWithInfo() []*DriverInfo {
72 driversMu.RLock()
73 defer driversMu.RUnlock()
74 infos := make([]*DriverInfo, 0, len(drivers))
75 for _, info := range drivers {
76 infos = append(infos, info)
77 }
78 // Sort by name for consistent output
79 sort.Slice(infos, func(i, j int) bool {
80 return infos[i].Name < infos[j].Name
81 })
82 return infos
83 }
84
85 // NewFromDriver creates a database using the named driver.
86 // Returns an error if the driver is not registered.
87 func NewFromDriver(ctx context.Context, cancel context.CancelFunc, driverName string, cfg *DatabaseConfig) (Database, error) {
88 factory := GetDriver(driverName)
89 if factory == nil {
90 return nil, errorf.E("database driver %q not available; registered: %v", driverName, ListDrivers())
91 }
92 return factory(ctx, cancel, cfg)
93 }
94