Files
herolib/lib/schemas/openapi/factory.v
2025-01-30 04:53:08 +03:00

97 lines
3.0 KiB
V

module openapi
import freeflowuniverse.herolib.schemas.jsonschema {Schema, SchemaRef, Reference}
import freeflowuniverse.herolib.core.texttools
import os
@[params]
pub struct Params {
pub:
path string // path to openrpc.json file
text string // content of openrpc specification text
}
pub fn new(params Params) !OpenAPI {
if params.path == '' && params.text == '' {
return error('Either provide path or text')
}
if params.text != '' && params.path != '' {
return error('Either provide path or text')
}
text := if params.path != '' {
os.read_file(params.path)!
} else { params.text }
specification := json_decode(text)!
return process(specification)!
}
fn process(spec OpenAPI) !OpenAPI {
mut processed := OpenAPI{...spec}
for key, schema in spec.components.schemas {
if schema is Schema {
mut processed_schema := Schema{
...schema,
id: if schema.id != '' { schema.id }
else if schema.title != '' { schema.title }
else { key }
title: if schema.title != '' { schema.title }
else if schema.id != '' { schema.id }
else { key }
}
processed.components.schemas[key] = processed_schema
}
}
for path, item in spec.paths {
mut processed_item := PathItem{...item}
processed_item.get = processed.process_operation(item.get, 'get', path)!
processed_item.post = processed.process_operation(item.post, 'post', path)!
processed_item.put = processed.process_operation(item.put, 'put', path)!
processed_item.delete = processed.process_operation(item.delete, 'delete', path)!
processed_item.patch = processed.process_operation(item.patch, 'patch', path)!
processed_item.options = processed.process_operation(item.options, 'options', path)!
processed_item.head = processed.process_operation(item.head, 'head', path)!
processed_item.trace = processed.process_operation(item.trace, 'trace', path)!
processed.paths[path] = processed_item
}
return processed
}
fn (spec OpenAPI) process_operation(op Operation, method string, path string) !Operation {
mut processed := Operation{...op}
if processed.operation_id == '' {
processed.operation_id = generate_operation_id(method, path)
}
if op.request_body is RequestBody {
if content := op.request_body.content['application/json'] {
if content.schema is Reference {
mut req_body_ := RequestBody{...op.request_body}
req_body_.content['application/json'].schema = SchemaRef(spec.dereference_schema(content.schema)!)
processed.request_body = RequestBodyRef(req_body_)
}
}
}
return processed
}
// Helper function to generate a unique operationId
fn generate_operation_id(method string, path string) string {
// Convert HTTP method and path into a camelCase string
method_part := method.to_lower()
path_part := path.all_before('{')
.replace('/', '_') // Replace slashes with underscores
.replace('{', '') // Remove braces around path parameters
.replace('}', '') // Remove braces around path parameters
return texttools.camel_case('${method_part}_${path_part}')
}