Files
herolib/lib/hero/baobab/generator/generate_handle.v
2025-03-13 12:39:38 +01:00

83 lines
3.0 KiB
V

module generator
import freeflowuniverse.herolib.core.code { CodeItem, CustomCode, VFile }
import freeflowuniverse.herolib.core.texttools
import freeflowuniverse.herolib.core.codeparser
import freeflowuniverse.herolib.data.markdownparser
import freeflowuniverse.herolib.data.markdownparser.elements
import freeflowuniverse.herolib.rpc.openrpc
import freeflowuniverse.herolib.core.pathlib
import freeflowuniverse.herolib.hero.baobab.specification { ActorMethod, ActorSpecification }
import os
import json
fn generate_handle_file(spec ActorSpecification) !VFile {
mut items := []CodeItem{}
items << CustomCode{generate_handle_function(spec)}
for method in spec.methods {
items << CustomCode{generate_method_handle(spec.name, method)!}
}
return VFile{
name: 'act'
items: items
}
}
pub fn generate_handle_function(spec ActorSpecification) string {
actor_name_pascal := texttools.name_fix_snake_to_pascal(spec.name)
mut operation_handlers := []string{}
mut routes := []string{}
// Iterate over OpenAPI paths and operations
for method in spec.methods {
operation_id := method.name
params := method.func.params.map(it.name).join(', ')
// Generate route case
route := generate_route_case(method.name, operation_id)
routes << route
}
// Combine the generated handlers and main router into a single file
return [
'// AUTO-GENERATED FILE - DO NOT EDIT MANUALLY',
'',
'pub fn (mut actor ${actor_name_pascal}Actor) act(action Action) !Response {',
' match action.name {',
routes.join('\n'),
' else {',
' return error("Unknown operation: \${req.operation.operation_id}")',
' }',
' }',
'}',
].join('\n')
}
pub fn generate_method_handle(actor_name string, method ActorMethod) !string {
actor_name_pascal := texttools.name_fix_snake_to_pascal(actor_name)
name_fixed := texttools.name_fix_snake(method.name)
mut handler := '// Handler for ${name_fixed}\n'
handler += 'fn (mut actor ${actor_name_pascal}Actor) handle_${name_fixed}(data string) !string {\n'
if method.func.params.len > 0 {
handler += ' params := json.decode(${method.func.params[0].typ.symbol}, data) or { return error("Invalid input data: \${err}") }\n'
handler += ' result := actor.${name_fixed}(params)\n'
} else {
handler += ' result := actor.${name_fixed}()\n'
}
handler += ' return json.encode(result)\n'
handler += '}'
return handler
}
// Helper function to generate a case block for the main router
fn generate_route_case(method string, operation_id string) string {
name_fixed := texttools.name_fix_snake(operation_id)
mut case_block := ' "${operation_id}" {'
case_block += '\n response := actor.handle_${name_fixed}(req.body) or {'
case_block += '\n return Response{ status: http.Status.internal_server_error, body: "Internal server error: \${err}" }'
case_block += '\n }'
case_block += '\n return Response{ status: http.Status.ok, body: response }'
case_block += '\n }'
return case_block
}