Chore: adapt debugapi to wakonodeconf (#3745)

* logosdelivery_get_available_configs collects and format WakuNodeConf options
* simplify debug config output
This commit is contained in:
NagyZoltanPeter 2026-03-03 23:48:00 +01:00 committed by GitHub
parent 1f9c4cb8cc
commit 4a6ad73235
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 161 additions and 8 deletions

View File

@ -1,5 +1,6 @@
import std/[json, strutils]
import waku/factory/waku_state_info
import tools/confutils/[cli_args, config_option_meta]
proc logosdelivery_get_available_node_info_ids(
ctx: ptr FFIContext[Waku], callback: FFICallBack, userData: pointer
@ -33,14 +34,21 @@ proc logosdelivery_get_available_configs(
ctx: ptr FFIContext[Waku], callback: FFICallBack, userData: pointer
) {.ffi.} =
## Returns information about the accepted config items.
## For analogy with a CLI app, this is the info when typing --help for a command.
requireInitializedNode(ctx, "GetAvailableConfigs"):
return err(errMsg)
## TODO: we are now returning a simple default value for NodeConfig.
## The NodeConfig struct is too complex and we need to have a flattened simpler config.
## The expected returned value for this is a list of possible config items with their
## description, accepted values, default value, etc.
let optionMetas: seq[ConfigOptionMeta] = extractConfigOptionMeta(WakuNodeConf)
var configOptionDetails = newJArray()
let defaultConfig = NodeConfig.init()
return ok($(%*defaultConfig))
# for confField, confValue in fieldPairs(conf):
# defaultConfig[confField] = $confValue
for meta in optionMetas:
configOptionDetails.add(
%*{meta.fieldName: meta.typeName & "(" & meta.defaultValue & ")", "desc": meta.desc}
)
var jsonNode = newJObject()
jsonNode["configOptions"] = configOptionDetails
let asString = pretty(jsonNode)
return ok(pretty(jsonNode))

View File

@ -480,7 +480,9 @@ with the drawback of consuming some more bandwidth.""",
## REST HTTP config
rest* {.
desc: "Enable Waku REST HTTP server: true|false", defaultValue: true, name: "rest"
desc: "Enable Waku REST HTTP server: true|false",
defaultValue: false,
name: "rest"
.}: bool
restAddress* {.

View File

@ -0,0 +1,143 @@
import std/[macros]
type ConfigOptionMeta* = object
fieldName*: string
typeName*: string
cliName*: string
desc*: string
defaultValue*: string
command*: string
proc getPragmaValue(pragmaNode: NimNode, pragmaName: string): string {.compileTime.} =
if pragmaNode.kind != nnkPragma:
return ""
for item in pragmaNode:
if item.kind == nnkExprColonExpr and item[0].eqIdent(pragmaName):
return item[1].repr
return ""
proc getFieldName(fieldNode: NimNode): string {.compileTime.} =
case fieldNode.kind
of nnkPragmaExpr:
if fieldNode.len >= 1:
return getFieldName(fieldNode[0])
of nnkPostfix:
if fieldNode.len >= 2:
return getFieldName(fieldNode[1])
of nnkIdent, nnkSym:
return fieldNode.strVal
else:
discard
return fieldNode.repr
proc getFieldAndPragma(
fieldDef: NimNode
): tuple[fieldName, typeName: string, pragmaNode: NimNode] {.compileTime.} =
if fieldDef.kind != nnkIdentDefs:
return ("", "", newNimNode(nnkEmpty))
let declaredField = fieldDef[0]
var typeNode = fieldDef[1]
var pragmaNode = newNimNode(nnkEmpty)
if declaredField.kind == nnkPragmaExpr:
pragmaNode = declaredField[1]
elif typeNode.kind == nnkPragmaExpr:
pragmaNode = typeNode[1]
typeNode = typeNode[0]
return (getFieldName(declaredField), typeNode.repr, pragmaNode)
proc makeMetaNode(
fieldName, typeName, cliName, desc, defaultValue, command: string
): NimNode {.compileTime.} =
result = newTree(
nnkObjConstr,
ident("ConfigOptionMeta"),
newTree(nnkExprColonExpr, ident("fieldName"), newLit(fieldName)),
newTree(nnkExprColonExpr, ident("typeName"), newLit(typeName)),
newTree(nnkExprColonExpr, ident("cliName"), newLit(cliName)),
newTree(nnkExprColonExpr, ident("desc"), newLit(desc)),
newTree(nnkExprColonExpr, ident("defaultValue"), newLit(defaultValue)),
newTree(nnkExprColonExpr, ident("command"), newLit(command)),
)
macro extractConfigOptionMeta*(T: typedesc): untyped =
proc findFirstRecList(n: NimNode): NimNode {.compileTime.} =
if n.kind == nnkRecList:
return n
for child in n:
let found = findFirstRecList(child)
if not found.isNil:
return found
return nil
proc collectRecList(
recList: NimNode, metas: var seq[NimNode], commandCtx: string
) {.compileTime.} =
for child in recList:
case child.kind
of nnkIdentDefs:
let (fieldName, typeName, pragmaNode) = getFieldAndPragma(child)
if fieldName.len == 0:
continue
let cliName = block:
let n = getPragmaValue(pragmaNode, "name")
if n.len > 0: n else: fieldName
let desc = getPragmaValue(pragmaNode, "desc")
let defaultValue = getPragmaValue(pragmaNode, "defaultValue")
metas.add(
makeMetaNode(fieldName, typeName, cliName, desc, defaultValue, commandCtx)
)
of nnkRecCase:
let discriminator = child[0]
if discriminator.kind == nnkIdentDefs:
let (fieldName, typeName, pragmaNode) = getFieldAndPragma(discriminator)
if fieldName.len > 0:
let cliName = block:
let n = getPragmaValue(pragmaNode, "name")
if n.len > 0: n else: fieldName
let desc = getPragmaValue(pragmaNode, "desc")
let defaultValue = getPragmaValue(pragmaNode, "defaultValue")
metas.add(
makeMetaNode(fieldName, typeName, cliName, desc, defaultValue, commandCtx)
)
for i in 1 ..< child.len:
let branch = child[i]
case branch.kind
of nnkOfBranch:
let branchCtx = branch[0].repr
for j in 1 ..< branch.len:
if branch[j].kind == nnkRecList:
collectRecList(branch[j], metas, branchCtx)
of nnkElse:
for j in 0 ..< branch.len:
if branch[j].kind == nnkRecList:
collectRecList(branch[j], metas, commandCtx)
else:
discard
else:
discard
let typeInst = getTypeInst(T)
var targetType = T
if typeInst.kind == nnkBracketExpr and typeInst.len >= 2:
targetType = typeInst[1]
let typeImpl = getImpl(targetType)
let recList = findFirstRecList(typeImpl)
if recList.isNil:
return newTree(nnkPrefix, ident("@"), newNimNode(nnkBracket))
var metas: seq[NimNode] = @[]
collectRecList(recList, metas, "")
let bracket = newNimNode(nnkBracket)
for node in metas:
bracket.add(node)
result = newTree(nnkPrefix, ident("@"), bracket)