Files
herolib/lib/baobab/specification/from_openapi.v

147 lines
4.4 KiB
V

module specification
import freeflowuniverse.herolib.core.code { Struct, Function }
import freeflowuniverse.herolib.schemas.jsonschema { Schema, SchemaRef }
import freeflowuniverse.herolib.schemas.openapi { Operation, Parameter, OpenAPI, Components, Info, PathItem, ServerSpec }
import freeflowuniverse.herolib.schemas.openrpc { ExamplePairing, Example, ExampleRef, ContentDescriptor, ErrorSpec }
// Helper function: Convert OpenAPI parameter to ContentDescriptor
fn openapi_param_to_content_descriptor(param Parameter) ContentDescriptor {
return ContentDescriptor{
name: param.name,
summary: param.description,
description: param.description,
required: param.required,
schema: param.schema
}
}
// Helper function: Convert OpenAPI parameter to ContentDescriptor
fn openapi_param_to_example(param Parameter) ?Example {
if param.schema is Schema {
if param.schema.example.str() != '' {
return Example{
name: 'Example ${param.name}',
description: 'Example ${param.description}',
value: param.schema.example
}
}
}
return none
}
// Helper function: Convert OpenAPI operation to ActorMethod
fn openapi_operation_to_actor_method(op Operation, method_name string, path string) ActorMethod {
mut parameters := []ContentDescriptor{}
mut example_parameters:= []Example{}
for param in op.parameters {
parameters << openapi_param_to_content_descriptor(param)
example_parameters << openapi_param_to_example(param) or {
continue
}
}
response_200 := op.responses['200'].content['application/json']
mut result := ContentDescriptor{
name: "result",
description: "The response of the operation.",
required: true,
schema: response_200.schema
}
example_result := if response_200.example.str() != '' {
Example{
name: 'Example response',
value: response_200.example
}
} else {Example{}}
pairing := if example_result != Example{} || example_parameters.len > 0 {
ExamplePairing{
params: example_parameters.map(ExampleRef(it))
result: ExampleRef(example_result)
}
} else {ExamplePairing{}}
mut errors := []ErrorSpec{}
for status, response in op.responses {
if status.int() >= 400 {
error_schema := if response.content.len > 0 {
response.content.values()[0].schema
} else {Schema{}}
errors << ErrorSpec{
code: status.int(),
message: response.description,
data: error_schema, // Extend if error schema is defined
}
}
}
return ActorMethod{
name: method_name,
description: op.description,
summary: op.summary,
parameters: parameters,
example: pairing
result: result,
errors: errors,
}
}
// Helper function: Convert OpenAPI schema to Struct
fn openapi_schema_to_struct(name string, schema SchemaRef) Struct {
// Assuming schema properties can be mapped to Struct fields
return Struct{
name: name,
}
}
// Converts OpenAPI to ActorSpecification
pub fn from_openapi(spec OpenAPI) !ActorSpecification {
mut methods := []ActorMethod{}
mut objects := []BaseObject{}
// Extract methods from OpenAPI paths
for path, item in spec.paths {
if item.get.operation_id != '' {
methods << openapi_operation_to_actor_method(item.get, item.get.operation_id, path)
}
if item.post.operation_id != '' {
methods << openapi_operation_to_actor_method(item.post, item.post.operation_id, path)
}
if item.put.operation_id != '' {
methods << openapi_operation_to_actor_method(item.put, item.put.operation_id, path)
}
if item.delete.operation_id != '' {
methods << openapi_operation_to_actor_method(item.delete, item.delete.operation_id, path)
}
if item.patch.operation_id != '' {
methods << openapi_operation_to_actor_method(item.patch, item.patch.operation_id, path)
}
if item.head.operation_id != '' {
methods << openapi_operation_to_actor_method(item.head, item.head.operation_id, path)
}
if item.options.operation_id != '' {
methods << openapi_operation_to_actor_method(item.options, item.options.operation_id, path)
}
if item.trace.operation_id != '' {
methods << openapi_operation_to_actor_method(item.trace, item.trace.operation_id, path)
}
}
// Extract objects from OpenAPI components.schemas
for name, schema in spec.components.schemas {
objects << BaseObject{schema as Schema}
}
return ActorSpecification{
name: spec.info.title,
description: spec.info.description,
structure: Struct{}, // Assuming no top-level structure for this use case
interfaces: [.openapi], // Default to OpenAPI for input
methods: methods,
objects: objects,
}
}