refactor: rename List method to Keys for clarity in configuration management

Signed-off-by: Deluan <deluan@navidrome.org>
This commit is contained in:
Deluan 2026-01-02 14:08:26 -05:00
parent 15a1d4152a
commit 3dba572ce7
10 changed files with 48 additions and 48 deletions

View File

@ -683,7 +683,7 @@ Access plugin configuration values programmatically. Unlike `pdk.GetConfig()` wh
|-----------------|------------|-----------------------------| |-----------------|------------|-----------------------------|
| `config_get` | `key` | `value, exists` | | `config_get` | `key` | `value, exists` |
| `config_getint` | `key` | `value, exists` | | `config_getint` | `key` | `value, exists` |
| `config_list` | `prefix` | Array of matching key names | | `config_keys` | `prefix` | Array of matching key names |
**Usage (with generated SDK):** **Usage (with generated SDK):**
@ -700,13 +700,13 @@ if exists {
count, exists := host.ConfigGetInt("max_retries") count, exists := host.ConfigGetInt("max_retries")
// List all keys with a prefix (useful for user-specific config) // List all keys with a prefix (useful for user-specific config)
keys := host.ConfigList("user:") keys := host.ConfigKeys("user:")
for _, key := range keys { for _, key := range keys {
// key might be "user:john", "user:jane", etc. // key might be "user:john", "user:jane", etc.
} }
// List all configuration keys // List all configuration keys
allKeys := host.ConfigList("") allKeys := host.ConfigKeys("")
``` ```
--- ---

View File

@ -33,12 +33,12 @@ type ConfigService interface {
//nd:hostfunc //nd:hostfunc
GetInt(ctx context.Context, key string) (value int64, exists bool) GetInt(ctx context.Context, key string) (value int64, exists bool)
// List returns configuration keys matching the given prefix. // Keys returns configuration keys matching the given prefix.
// //
// Parameters: // Parameters:
// - prefix: Key prefix to filter by. If empty, returns all keys. // - prefix: Key prefix to filter by. If empty, returns all keys.
// //
// Returns a sorted slice of matching configuration keys. // Returns a sorted slice of matching configuration keys.
//nd:hostfunc //nd:hostfunc
List(ctx context.Context, prefix string) (keys []string) Keys(ctx context.Context, prefix string) (keys []string)
} }

View File

@ -31,13 +31,13 @@ type ConfigGetIntResponse struct {
Exists bool `json:"exists,omitempty"` Exists bool `json:"exists,omitempty"`
} }
// ConfigListRequest is the request type for Config.List. // ConfigKeysRequest is the request type for Config.Keys.
type ConfigListRequest struct { type ConfigKeysRequest struct {
Prefix string `json:"prefix"` Prefix string `json:"prefix"`
} }
// ConfigListResponse is the response type for Config.List. // ConfigKeysResponse is the response type for Config.Keys.
type ConfigListResponse struct { type ConfigKeysResponse struct {
Keys []string `json:"keys,omitempty"` Keys []string `json:"keys,omitempty"`
} }
@ -47,7 +47,7 @@ func RegisterConfigHostFunctions(service ConfigService) []extism.HostFunction {
return []extism.HostFunction{ return []extism.HostFunction{
newConfigGetHostFunction(service), newConfigGetHostFunction(service),
newConfigGetIntHostFunction(service), newConfigGetIntHostFunction(service),
newConfigListHostFunction(service), newConfigKeysHostFunction(service),
} }
} }
@ -113,9 +113,9 @@ func newConfigGetIntHostFunction(service ConfigService) extism.HostFunction {
) )
} }
func newConfigListHostFunction(service ConfigService) extism.HostFunction { func newConfigKeysHostFunction(service ConfigService) extism.HostFunction {
return extism.NewHostFunctionWithStack( return extism.NewHostFunctionWithStack(
"config_list", "config_keys",
func(ctx context.Context, p *extism.CurrentPlugin, stack []uint64) { func(ctx context.Context, p *extism.CurrentPlugin, stack []uint64) {
// Read JSON request from plugin memory // Read JSON request from plugin memory
reqBytes, err := p.ReadBytes(stack[0]) reqBytes, err := p.ReadBytes(stack[0])
@ -123,17 +123,17 @@ func newConfigListHostFunction(service ConfigService) extism.HostFunction {
configWriteError(p, stack, err) configWriteError(p, stack, err)
return return
} }
var req ConfigListRequest var req ConfigKeysRequest
if err := json.Unmarshal(reqBytes, &req); err != nil { if err := json.Unmarshal(reqBytes, &req); err != nil {
configWriteError(p, stack, err) configWriteError(p, stack, err)
return return
} }
// Call the service method // Call the service method
keys := service.List(ctx, req.Prefix) keys := service.Keys(ctx, req.Prefix)
// Write JSON response to plugin memory // Write JSON response to plugin memory
resp := ConfigListResponse{ resp := ConfigKeysResponse{
Keys: keys, Keys: keys,
} }
configWriteResponse(p, stack, resp) configWriteResponse(p, stack, resp)

View File

@ -53,8 +53,8 @@ func (s *configServiceImpl) GetInt(ctx context.Context, key string) (int64, bool
return intValue, true return intValue, true
} }
// List returns configuration keys matching the given prefix. // Keys returns configuration keys matching the given prefix.
func (s *configServiceImpl) List(ctx context.Context, prefix string) []string { func (s *configServiceImpl) Keys(ctx context.Context, prefix string) []string {
keys := make([]string, 0, len(s.config)) keys := make([]string, 0, len(s.config))
for k := range s.config { for k := range s.config {
if prefix == "" || strings.HasPrefix(k, prefix) { if prefix == "" || strings.HasPrefix(k, prefix) {
@ -62,7 +62,7 @@ func (s *configServiceImpl) List(ctx context.Context, prefix string) []string {
} }
} }
sort.Strings(keys) sort.Strings(keys)
log.Trace(ctx, "Config.List", "plugin", s.pluginName, "prefix", prefix, "keyCount", len(keys)) log.Trace(ctx, "Config.Keys", "plugin", s.pluginName, "prefix", prefix, "keyCount", len(keys))
return keys return keys
} }

View File

@ -107,7 +107,7 @@ var _ = Describe("ConfigService", func() {
}) })
}) })
Describe("List", func() { Describe("Keys", func() {
BeforeEach(func() { BeforeEach(func() {
service = newConfigService("test_plugin", map[string]string{ service = newConfigService("test_plugin", map[string]string{
"zebra": "z", "zebra": "z",
@ -120,23 +120,23 @@ var _ = Describe("ConfigService", func() {
}) })
It("returns all keys in sorted order when prefix is empty", func() { It("returns all keys in sorted order when prefix is empty", func() {
keys := service.List(ctx, "") keys := service.Keys(ctx, "")
Expect(keys).To(Equal([]string{"apple", "banana", "user_alice", "user_bob", "user_charlie", "zebra"})) Expect(keys).To(Equal([]string{"apple", "banana", "user_alice", "user_bob", "user_charlie", "zebra"}))
}) })
It("returns only keys matching prefix", func() { It("returns only keys matching prefix", func() {
keys := service.List(ctx, "user_") keys := service.Keys(ctx, "user_")
Expect(keys).To(Equal([]string{"user_alice", "user_bob", "user_charlie"})) Expect(keys).To(Equal([]string{"user_alice", "user_bob", "user_charlie"}))
}) })
It("returns empty slice when no keys match prefix", func() { It("returns empty slice when no keys match prefix", func() {
keys := service.List(ctx, "nonexistent_") keys := service.Keys(ctx, "nonexistent_")
Expect(keys).To(BeEmpty()) Expect(keys).To(BeEmpty())
}) })
It("returns empty slice for empty config", func() { It("returns empty slice for empty config", func() {
service = newConfigService("test_plugin", nil) service = newConfigService("test_plugin", nil)
keys := service.List(ctx, "") keys := service.Keys(ctx, "")
Expect(keys).To(BeEmpty()) Expect(keys).To(BeEmpty())
}) })
}) })

View File

@ -23,10 +23,10 @@ func config_get(uint64) uint64
//go:wasmimport extism:host/user config_getint //go:wasmimport extism:host/user config_getint
func config_getint(uint64) uint64 func config_getint(uint64) uint64
// config_list is the host function provided by Navidrome. // config_keys is the host function provided by Navidrome.
// //
//go:wasmimport extism:host/user config_list //go:wasmimport extism:host/user config_keys
func config_list(uint64) uint64 func config_keys(uint64) uint64
type configGetRequest struct { type configGetRequest struct {
Key string `json:"key"` Key string `json:"key"`
@ -46,11 +46,11 @@ type configGetIntResponse struct {
Exists bool `json:"exists,omitempty"` Exists bool `json:"exists,omitempty"`
} }
type configListRequest struct { type configKeysRequest struct {
Prefix string `json:"prefix"` Prefix string `json:"prefix"`
} }
type configListResponse struct { type configKeysResponse struct {
Keys []string `json:"keys,omitempty"` Keys []string `json:"keys,omitempty"`
} }
@ -125,16 +125,16 @@ func ConfigGetInt(key string) (int64, bool) {
return response.Value, response.Exists return response.Value, response.Exists
} }
// ConfigList calls the config_list host function. // ConfigKeys calls the config_keys host function.
// List returns configuration keys matching the given prefix. // List returns configuration keys matching the given prefix.
// //
// Parameters: // Parameters:
// - prefix: Key prefix to filter by. If empty, returns all keys. // - prefix: Key prefix to filter by. If empty, returns all keys.
// //
// Returns a sorted slice of matching configuration keys. // Returns a sorted slice of matching configuration keys.
func ConfigList(prefix string) []string { func ConfigKeys(prefix string) []string {
// Marshal request to JSON // Marshal request to JSON
req := configListRequest{ req := configKeysRequest{
Prefix: prefix, Prefix: prefix,
} }
reqBytes, err := json.Marshal(req) reqBytes, err := json.Marshal(req)
@ -145,14 +145,14 @@ func ConfigList(prefix string) []string {
defer reqMem.Free() defer reqMem.Free()
// Call the host function // Call the host function
responsePtr := config_list(reqMem.Offset()) responsePtr := config_keys(reqMem.Offset())
// Read the response from memory // Read the response from memory
responseMem := pdk.FindMemory(responsePtr) responseMem := pdk.FindMemory(responsePtr)
responseBytes := responseMem.ReadBytes() responseBytes := responseMem.ReadBytes()
// Parse the response // Parse the response
var response configListResponse var response configKeysResponse
if err := json.Unmarshal(responseBytes, &response); err != nil { if err := json.Unmarshal(responseBytes, &response); err != nil {
return nil return nil
} }

View File

@ -54,19 +54,19 @@ func ConfigGetInt(key string) (int64, bool) {
return ConfigMock.GetInt(key) return ConfigMock.GetInt(key)
} }
// List is the mock method for ConfigList. // Keys is the mock method for ConfigKeys.
func (m *mockConfigService) List(prefix string) []string { func (m *mockConfigService) Keys(prefix string) []string {
args := m.Called(prefix) args := m.Called(prefix)
return args.Get(0).([]string) return args.Get(0).([]string)
} }
// ConfigList delegates to the mock instance. // ConfigKeys delegates to the mock instance.
// List returns configuration keys matching the given prefix. // List returns configuration keys matching the given prefix.
// //
// Parameters: // Parameters:
// - prefix: Key prefix to filter by. If empty, returns all keys. // - prefix: Key prefix to filter by. If empty, returns all keys.
// //
// Returns a sorted slice of matching configuration keys. // Returns a sorted slice of matching configuration keys.
func ConfigList(prefix string) []string { func ConfigKeys(prefix string) []string {
return ConfigMock.List(prefix) return ConfigMock.Keys(prefix)
} }

View File

@ -31,8 +31,8 @@ def _config_getint(offset: int) -> int:
... ...
@extism.import_fn("extism:host/user", "config_list") @extism.import_fn("extism:host/user", "config_keys")
def _config_list(offset: int) -> int: def _config_keys(offset: int) -> int:
"""Raw host function - do not call directly.""" """Raw host function - do not call directly."""
... ...
@ -116,7 +116,7 @@ value cannot be parsed as an integer, exists will be false.
) )
def config_list(prefix: str) -> Any: def config_keys(prefix: str) -> Any:
"""List returns configuration keys matching the given prefix. """List returns configuration keys matching the given prefix.
Parameters: Parameters:
@ -138,7 +138,7 @@ Returns a sorted slice of matching configuration keys.
} }
request_bytes = json.dumps(request).encode("utf-8") request_bytes = json.dumps(request).encode("utf-8")
request_mem = extism.memory.alloc(request_bytes) request_mem = extism.memory.alloc(request_bytes)
response_offset = _config_list(request_mem.offset) response_offset = _config_keys(request_mem.offset)
response_mem = extism.memory.find(response_offset) response_mem = extism.memory.find(response_offset)
response = json.loads(extism.memory.string(response_mem)) response = json.loads(extism.memory.string(response_mem))

View File

@ -38,13 +38,13 @@ struct ConfigGetIntResponse {
#[derive(Debug, Clone, Serialize)] #[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
struct ConfigListRequest { struct ConfigKeysRequest {
prefix: String, prefix: String,
} }
#[derive(Debug, Clone, Deserialize)] #[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
struct ConfigListResponse { struct ConfigKeysResponse {
#[serde(default)] #[serde(default)]
keys: Vec<String>, keys: Vec<String>,
} }
@ -53,7 +53,7 @@ struct ConfigListResponse {
extern "ExtismHost" { extern "ExtismHost" {
fn config_get(input: Json<ConfigGetRequest>) -> Json<ConfigGetResponse>; fn config_get(input: Json<ConfigGetRequest>) -> Json<ConfigGetResponse>;
fn config_getint(input: Json<ConfigGetIntRequest>) -> Json<ConfigGetIntResponse>; fn config_getint(input: Json<ConfigGetIntRequest>) -> Json<ConfigGetIntResponse>;
fn config_list(input: Json<ConfigListRequest>) -> Json<ConfigListResponse>; fn config_keys(input: Json<ConfigKeysRequest>) -> Json<ConfigKeysResponse>;
} }
/// Get retrieves a configuration value as a string. /// Get retrieves a configuration value as a string.
@ -122,9 +122,9 @@ pub fn get_int(key: &str) -> Result<(i64, bool), Error> {
/// ///
/// # Errors /// # Errors
/// Returns an error if the host function call fails. /// Returns an error if the host function call fails.
pub fn list(prefix: &str) -> Result<Vec<String>, Error> { pub fn keys(prefix: &str) -> Result<Vec<String>, Error> {
let response = unsafe { let response = unsafe {
config_list(Json(ConfigListRequest { config_keys(Json(ConfigKeysRequest {
prefix: prefix.to_owned(), prefix: prefix.to_owned(),
}))? }))?
}; };

View File

@ -46,7 +46,7 @@ func ndTestConfig() int32 {
return 0 return 0
case "list": case "list":
keys := host.ConfigList(input.Prefix) keys := host.ConfigKeys(input.Prefix)
pdk.OutputJSON(TestConfigOutput{Keys: keys}) pdk.OutputJSON(TestConfigOutput{Keys: keys})
return 0 return 0