fix actor generation and tests

This commit is contained in:
timurgordon
2025-01-03 01:47:16 -05:00
parent ce1ce722d5
commit d5af1d19b8
9 changed files with 328 additions and 181 deletions

View File

@@ -2,7 +2,8 @@ module generator
import freeflowuniverse.herolib.core.code { Folder, IFile, VFile, CodeItem, File, Function, Import, Module, Struct, CustomCode }
import freeflowuniverse.herolib.core.texttools
import freeflowuniverse.herolib.schemas.openrpc
import freeflowuniverse.herolib.schemas.openrpc {ContentDescriptor}
import freeflowuniverse.herolib.schemas.jsonschema.codegen {schemaref_to_type}
import freeflowuniverse.herolib.baobab.specification {ActorMethod, ActorSpecification}
import os
import json
@@ -15,6 +16,7 @@ fn generate_handle_file(spec ActorSpecification) !VFile {
}
return VFile {
name: 'act'
imports: [Import{mod:'freeflowuniverse.herolib.baobab.actions' types:['Action']}]
items: items
}
}
@@ -38,11 +40,11 @@ pub fn generate_handle_function(spec ActorSpecification) string {
return [
'// AUTO-GENERATED FILE - DO NOT EDIT MANUALLY',
'',
'pub fn (mut actor ${actor_name_pascal}Actor) act(action Action) !Response {',
'pub fn (mut actor ${actor_name_pascal}Actor) act(action Action) !Action {',
' match action.name {',
routes.join('\n'),
' else {',
' return error("Unknown operation: \${req.operation.operation_id}")',
' return error("Unknown operation: \${action.name}")',
' }',
' }',
'}',
@@ -52,28 +54,72 @@ pub fn generate_handle_function(spec ActorSpecification) string {
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)
if name_fixed == "create_pet" {
println('debug ${method}')
}
mut handler := '// Handler for ${name_fixed}\n'
handler += "fn (mut actor ${actor_name_pascal}Actor) handle_${name_fixed}(data string) !string {\n"
if method.parameters.len > 0 {
params_zero := method.parameters[0].name
handler += ' params := json.decode(${params_zero}, data) or { return error("Invalid input data: \${err}") }\n'
handler += ' result := actor.${name_fixed}(params)\n'
} else {
handler += ' result := actor.${name_fixed}()\n'
if method.parameters.len == 1 {
param := method.parameters[0]
param_name := texttools.name_fix_snake(param.name)
decode_stmt := generate_decode_stmt('data', param)!
handler += '${param_name} := ${decode_stmt}\n'
}
handler += ' return json.encode(result)\n'
if method.parameters.len > 1 {
handler += 'params_arr := json2.raw_decode(data).arr()\n'
for i, param in method.parameters {
param_name := texttools.name_fix_snake(param.name)
decode_stmt := generate_decode_stmt('params_arr[${i}]', param)!
handler += '${param_name} := ${decode_stmt}'
}
// params_zero := schema_to_type(method.parameters[0].schema)
// handler += ' params := json.decode(${params_zero}, data) or { return error("Invalid input data: \${err}") }\n'
// handler += ' result := actor.${name_fixed}(params)\n'
}
call_stmt := generate_call_stmt(method)!
handler += '${call_stmt}\n'
handler += '${generate_return_stmt(method)!}\n'
handler += '}'
return handler
}
fn generate_call_stmt(method ActorMethod) !string {
mut call_stmt := if schemaref_to_type(method.result.schema)!.vgen().trim_space() != '' {
'${method.result.name} := '
} else {''}
name_fixed := texttools.name_fix_snake(method.name)
param_names := method.parameters.map(texttools.name_fix_snake(it.name))
call_stmt += 'actor.${name_fixed}(${param_names.join(", ")})!'
return call_stmt
}
fn generate_return_stmt(method ActorMethod) !string {
if schemaref_to_type(method.result.schema)!.vgen().trim_space() != '' {
return 'return json.encode(${method.result.name})'
}
return "return ''"
}
// generates decode statement for variable with given name
fn generate_decode_stmt(name string, param ContentDescriptor) !string {
param_type := schemaref_to_type(param.schema)!
if param_type.vgen().is_capital() {
return 'json2.decode[${schemaref_to_type(param.schema)!.vgen()}](${name})'
}
// else if param.schema.typ == 'array' {
// return 'json2.decode[${schemaref_to_type(param.schema)!.vgen()}](${name})'
// }
return '${name}.${param_type.vgen()}()'
}
// 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 response := actor.handle_${name_fixed}(action.params) or {'
case_block += '\n return Action{ result: err.msg() }'
case_block += '\n }'
case_block += '\n return Response{ status: http.Status.ok, body: response }'
case_block += '\n return Action{ result: response }'
case_block += '\n }'
return case_block
}