openrpc to actor spec base object fixes
This commit is contained in:
@@ -8,212 +8,147 @@ import os
|
||||
|
||||
const actor_spec = specification.ActorSpecification{
|
||||
name: 'Pet Store'
|
||||
description: 'A sample API for a pet store'
|
||||
interfaces: [.openapi]
|
||||
structure: code.Struct{}
|
||||
interfaces: [.openrpc]
|
||||
methods: [
|
||||
specification.ActorMethod{
|
||||
name: 'listPets'
|
||||
name: 'list_pets'
|
||||
summary: 'List all pets'
|
||||
parameters: [
|
||||
openrpc.ContentDescriptor{
|
||||
name: 'limit'
|
||||
summary: 'Maximum number of pets to return'
|
||||
description: 'Maximum number of pets to return'
|
||||
schema: jsonschema.SchemaRef(jsonschema.Schema{
|
||||
typ: 'integer'
|
||||
format: 'int32'
|
||||
})
|
||||
}
|
||||
]
|
||||
result: openrpc.ContentDescriptor{
|
||||
name: 'result'
|
||||
description: 'The response of the operation.'
|
||||
schema: jsonschema.SchemaRef(jsonschema.Reference{
|
||||
ref: '#/components/schemas/Pets'
|
||||
parameters: [openrpc.ContentDescriptor{
|
||||
name: 'limit'
|
||||
description: 'How many items to return at one time (max 100)'
|
||||
required: false
|
||||
schema: jsonschema.SchemaRef(jsonschema.Schema{
|
||||
typ: 'integer'
|
||||
minimum: 1
|
||||
})
|
||||
}
|
||||
errors: [
|
||||
openrpc.ErrorSpec{
|
||||
code: 400
|
||||
message: 'Invalid request'
|
||||
}
|
||||
]
|
||||
},
|
||||
specification.ActorMethod{
|
||||
name: 'createPet'
|
||||
summary: 'Create a new pet'
|
||||
}]
|
||||
result: openrpc.ContentDescriptor{
|
||||
name: 'result'
|
||||
description: 'The response of the operation.'
|
||||
}
|
||||
errors: [
|
||||
openrpc.ErrorSpec{
|
||||
code: 400
|
||||
message: 'Invalid input'
|
||||
}
|
||||
]
|
||||
},
|
||||
specification.ActorMethod{
|
||||
name: 'getPet'
|
||||
summary: 'Get a pet by ID'
|
||||
parameters: [
|
||||
openrpc.ContentDescriptor{
|
||||
name: 'petId'
|
||||
summary: 'ID of the pet to retrieve'
|
||||
description: 'ID of the pet to retrieve'
|
||||
schema: jsonschema.SchemaRef(jsonschema.Schema{
|
||||
typ: 'integer'
|
||||
format: 'int64'
|
||||
})
|
||||
}
|
||||
]
|
||||
result: openrpc.ContentDescriptor{
|
||||
name: 'result'
|
||||
description: 'The response of the operation.'
|
||||
schema: jsonschema.SchemaRef(jsonschema.Reference{
|
||||
ref: '#/components/schemas/Pet'
|
||||
})
|
||||
}
|
||||
errors: [
|
||||
openrpc.ErrorSpec{
|
||||
code: 404
|
||||
message: 'Pet not found'
|
||||
}
|
||||
]
|
||||
},
|
||||
specification.ActorMethod{
|
||||
name: 'deletePet'
|
||||
summary: 'Delete a pet by ID'
|
||||
parameters: [
|
||||
openrpc.ContentDescriptor{
|
||||
name: 'petId'
|
||||
summary: 'ID of the pet to delete'
|
||||
description: 'ID of the pet to delete'
|
||||
schema: jsonschema.SchemaRef(jsonschema.Schema{
|
||||
typ: 'integer'
|
||||
format: 'int64'
|
||||
})
|
||||
}
|
||||
]
|
||||
result: openrpc.ContentDescriptor{
|
||||
name: 'result'
|
||||
description: 'The response of the operation.'
|
||||
}
|
||||
errors: [
|
||||
openrpc.ErrorSpec{
|
||||
code: 404
|
||||
message: 'Pet not found'
|
||||
}
|
||||
]
|
||||
},
|
||||
specification.ActorMethod{
|
||||
name: 'listOrders'
|
||||
summary: 'List all orders'
|
||||
result: openrpc.ContentDescriptor{
|
||||
name: 'result'
|
||||
description: 'The response of the operation.'
|
||||
name: 'pets'
|
||||
description: 'A paged array of pets'
|
||||
schema: jsonschema.SchemaRef(jsonschema.Schema{
|
||||
typ: 'array'
|
||||
items: jsonschema.Items(jsonschema.SchemaRef(jsonschema.Reference{
|
||||
ref: '#/components/schemas/Order'
|
||||
ref: '#/components/schemas/Pet'
|
||||
}))
|
||||
})
|
||||
}
|
||||
},
|
||||
specification.ActorMethod{
|
||||
name: 'getOrder'
|
||||
summary: 'Get an order by ID'
|
||||
name: 'create_pet'
|
||||
summary: 'Create a pet'
|
||||
parameters: [
|
||||
openrpc.ContentDescriptor{
|
||||
name: 'orderId'
|
||||
summary: 'ID of the order to retrieve'
|
||||
description: 'ID of the order to retrieve'
|
||||
name: 'newPetName'
|
||||
description: 'Name of pet to create'
|
||||
required: true
|
||||
schema: jsonschema.SchemaRef(jsonschema.Schema{
|
||||
typ: 'integer'
|
||||
format: 'int64'
|
||||
typ: 'string'
|
||||
})
|
||||
},
|
||||
openrpc.ContentDescriptor{
|
||||
name: 'newPetTag'
|
||||
description: 'Pet tag to create'
|
||||
schema: jsonschema.SchemaRef(jsonschema.Schema{
|
||||
typ: 'string'
|
||||
})
|
||||
}
|
||||
]
|
||||
result: openrpc.ContentDescriptor{
|
||||
name: 'result'
|
||||
description: 'The response of the operation.'
|
||||
schema: jsonschema.SchemaRef(jsonschema.Reference{
|
||||
ref: '#/components/schemas/Order'
|
||||
name: 'petId'
|
||||
description: 'The ID of the created pet'
|
||||
schema: jsonschema.SchemaRef(jsonschema.Schema{
|
||||
typ: 'integer'
|
||||
})
|
||||
}
|
||||
errors: [
|
||||
openrpc.ErrorSpec{
|
||||
code: 404
|
||||
message: 'Order not found'
|
||||
}
|
||||
]
|
||||
},
|
||||
specification.ActorMethod{
|
||||
name: 'deleteOrder'
|
||||
summary: 'Delete an order by ID'
|
||||
name: 'get_pet'
|
||||
summary: 'Info for a specific pet'
|
||||
parameters: [openrpc.ContentDescriptor{
|
||||
name: 'petId'
|
||||
description: 'The ID of the pet to retrieve'
|
||||
required: true
|
||||
schema: jsonschema.SchemaRef(jsonschema.Schema{
|
||||
typ: 'integer'
|
||||
})
|
||||
}]
|
||||
result: openrpc.ContentDescriptor{
|
||||
name: 'pet'
|
||||
description: 'The pet details'
|
||||
schema: jsonschema.SchemaRef(jsonschema.Reference{
|
||||
ref: '#/components/schemas/Pet'
|
||||
})
|
||||
}
|
||||
},
|
||||
specification.ActorMethod{
|
||||
name: 'update_pet'
|
||||
summary: 'Update a pet'
|
||||
parameters: [
|
||||
openrpc.ContentDescriptor{
|
||||
name: 'orderId'
|
||||
summary: 'ID of the order to delete'
|
||||
description: 'ID of the order to delete'
|
||||
name: 'petId'
|
||||
description: 'The ID of the pet to update'
|
||||
required: true
|
||||
schema: jsonschema.SchemaRef(jsonschema.Schema{
|
||||
typ: 'integer'
|
||||
format: 'int64'
|
||||
})
|
||||
},
|
||||
openrpc.ContentDescriptor{
|
||||
name: 'updatedPetName'
|
||||
description: 'New name for the pet'
|
||||
schema: jsonschema.SchemaRef(jsonschema.Schema{
|
||||
typ: 'string'
|
||||
})
|
||||
},
|
||||
openrpc.ContentDescriptor{
|
||||
name: 'updatedPetTag'
|
||||
description: 'New tag for the pet'
|
||||
schema: jsonschema.SchemaRef(jsonschema.Schema{
|
||||
typ: 'string'
|
||||
})
|
||||
}
|
||||
]
|
||||
result: openrpc.ContentDescriptor{
|
||||
name: 'result'
|
||||
description: 'The response of the operation.'
|
||||
name: 'pet'
|
||||
description: 'The updated pet object'
|
||||
schema: jsonschema.SchemaRef(jsonschema.Reference{
|
||||
ref: '#/components/schemas/Pet'
|
||||
})
|
||||
}
|
||||
errors: [
|
||||
openrpc.ErrorSpec{
|
||||
code: 404
|
||||
message: 'Order not found'
|
||||
}
|
||||
]
|
||||
},
|
||||
specification.ActorMethod{
|
||||
name: 'createUser'
|
||||
summary: 'Create a user'
|
||||
result: openrpc.ContentDescriptor{
|
||||
name: 'result'
|
||||
description: 'The response of the operation.'
|
||||
}
|
||||
name: 'delete_pet'
|
||||
summary: 'Delete a pet'
|
||||
parameters: [openrpc.ContentDescriptor{
|
||||
name: 'petId'
|
||||
description: 'The ID of the pet to delete'
|
||||
required: true
|
||||
schema: jsonschema.SchemaRef(jsonschema.Schema{
|
||||
typ: 'integer'
|
||||
})
|
||||
}]
|
||||
}
|
||||
]
|
||||
objects: [
|
||||
specification.BaseObject{
|
||||
structure: code.Struct{
|
||||
name: 'Pet'
|
||||
}
|
||||
},
|
||||
specification.BaseObject{
|
||||
structure: code.Struct{
|
||||
name: 'NewPet'
|
||||
}
|
||||
},
|
||||
specification.BaseObject{
|
||||
structure: code.Struct{
|
||||
name: 'Pets'
|
||||
}
|
||||
},
|
||||
specification.BaseObject{
|
||||
structure: code.Struct{
|
||||
name: 'Order'
|
||||
}
|
||||
},
|
||||
specification.BaseObject{
|
||||
structure: code.Struct{
|
||||
name: 'User'
|
||||
}
|
||||
},
|
||||
specification.BaseObject{
|
||||
structure: code.Struct{
|
||||
name: 'NewUser'
|
||||
objects: [specification.BaseObject{
|
||||
schema: jsonschema.Schema{
|
||||
id: 'pet'
|
||||
title: 'Pet'
|
||||
description: 'A pet object'
|
||||
typ: 'object'
|
||||
properties: {
|
||||
'id': jsonschema.SchemaRef(jsonschema.Schema{
|
||||
typ: 'integer'
|
||||
}),
|
||||
'name': jsonschema.SchemaRef(jsonschema.Schema{
|
||||
typ: 'string'
|
||||
}),
|
||||
'tag': jsonschema.SchemaRef(jsonschema.Schema{
|
||||
typ: 'string'
|
||||
})
|
||||
}
|
||||
required: ['id', 'name']
|
||||
}
|
||||
]
|
||||
}]
|
||||
}
|
||||
|
||||
const destination = '${os.dir(@FILE)}/testdata'
|
||||
|
||||
@@ -2,6 +2,7 @@ module generator
|
||||
|
||||
import freeflowuniverse.herolib.core.code { Folder, IFile, VFile, CodeItem, File, Function, Param, Import, Module, Struct, CustomCode }
|
||||
import freeflowuniverse.herolib.core.texttools
|
||||
import freeflowuniverse.herolib.schemas.jsonschema.codegen {schema_to_struct}
|
||||
import freeflowuniverse.herolib.baobab.specification {ActorMethod, ActorSpecification}
|
||||
|
||||
pub fn generate_model_file(spec ActorSpecification) !VFile {
|
||||
@@ -10,6 +11,9 @@ pub fn generate_model_file(spec ActorSpecification) !VFile {
|
||||
|
||||
return VFile {
|
||||
name: 'model'
|
||||
items: spec.objects.map(CodeItem(it.structure))
|
||||
items: spec.objects.map(CodeItem(
|
||||
Struct {...schema_to_struct(it.schema)!
|
||||
is_pub: true
|
||||
}))
|
||||
}
|
||||
}
|
||||
@@ -97,11 +97,7 @@ pub fn from_openapi(spec OpenAPI) !ActorSpecification {
|
||||
|
||||
// Extract objects from OpenAPI components.schemas
|
||||
for name, schema in spec.components.schemas {
|
||||
objects << BaseObject{
|
||||
structure: openapi_schema_to_struct(name, schema),
|
||||
methods: []Function{}, // Add related methods if applicable
|
||||
children: []Struct{}, // Add nested structures if defined
|
||||
}
|
||||
objects << BaseObject{schema as Schema}
|
||||
}
|
||||
|
||||
return ActorSpecification{
|
||||
|
||||
@@ -2,6 +2,7 @@ module specification
|
||||
|
||||
import freeflowuniverse.herolib.schemas.openrpc { OpenRPC, Method, ContentDescriptor, ErrorSpec }
|
||||
import freeflowuniverse.herolib.schemas.jsonschema { Reference, Schema, SchemaRef }
|
||||
import freeflowuniverse.herolib.core.texttools
|
||||
|
||||
// Helper function: Convert OpenRPC Method to ActorMethod
|
||||
fn openrpc_method_to_actor_method(method Method) ActorMethod {
|
||||
@@ -76,16 +77,23 @@ pub fn from_openrpc(spec OpenRPC) !ActorSpecification {
|
||||
|
||||
// Process methods
|
||||
for method in spec.methods {
|
||||
methods << openrpc_method_to_actor_method(method)
|
||||
methods << openrpc_method_to_actor_method(spec.inflate_method(method))
|
||||
}
|
||||
|
||||
// Process objects (schemas)
|
||||
// structs := extract_structs_from_openrpc(spec)
|
||||
// for structure in structs {
|
||||
// objects << BaseObject{
|
||||
// structure: structure
|
||||
// }
|
||||
// }
|
||||
for key, schema in spec.components.schemas {
|
||||
if schema is Schema {
|
||||
if schema.typ == 'object' {
|
||||
objects << BaseObject{
|
||||
schema: Schema {...schema,
|
||||
title: texttools.name_fix_pascal(key)
|
||||
id: texttools.name_fix_snake(key)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ActorSpecification{
|
||||
name: spec.info.title
|
||||
|
||||
@@ -5,563 +5,317 @@ import freeflowuniverse.herolib.schemas.openrpc { ContentDescriptor, ErrorSpec }
|
||||
import freeflowuniverse.herolib.schemas.openapi { OpenAPI, Info, ServerSpec, Components, Operation, PathItem, PathRef }
|
||||
import freeflowuniverse.herolib.schemas.jsonschema {Schema, Reference, SchemaRef}
|
||||
|
||||
const openapi_spec = openapi.OpenAPI{
|
||||
openapi: '3.0.3'
|
||||
info: openapi.Info{
|
||||
title: 'Pet Store API'
|
||||
description: 'A sample API for a pet store'
|
||||
version: '1.0.0'
|
||||
}
|
||||
servers: [
|
||||
openapi.ServerSpec{
|
||||
url: 'https://api.petstore.example.com/v1'
|
||||
description: 'Production server'
|
||||
},
|
||||
openapi.ServerSpec{
|
||||
url: 'https://staging.petstore.example.com/v1'
|
||||
description: 'Staging server'
|
||||
}
|
||||
]
|
||||
paths: {
|
||||
'/pets': openapi.PathItem{
|
||||
get: openapi.Operation{
|
||||
summary: 'List all pets'
|
||||
operation_id: 'listPets'
|
||||
parameters: [
|
||||
openapi.Parameter{
|
||||
name: 'limit'
|
||||
in_: 'query'
|
||||
description: 'Maximum number of pets to return'
|
||||
required: false
|
||||
schema: Schema{
|
||||
typ: 'integer'
|
||||
format: 'int32'
|
||||
}
|
||||
}
|
||||
]
|
||||
responses: {
|
||||
'200': openapi.ResponseSpec{
|
||||
description: 'A paginated list of pets'
|
||||
content: {
|
||||
'application/json': openapi.MediaType{
|
||||
schema: Reference{
|
||||
ref: '#/components/schemas/Pets'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
'400': openapi.ResponseSpec{
|
||||
description: 'Invalid request'
|
||||
}
|
||||
}
|
||||
}
|
||||
post: openapi.Operation{
|
||||
summary: 'Create a new pet'
|
||||
operation_id: 'createPet'
|
||||
request_body: openapi.RequestBody{
|
||||
required: true
|
||||
content: {
|
||||
'application/json': openapi.MediaType{
|
||||
schema: Reference{
|
||||
ref: '#/components/schemas/NewPet'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
responses: {
|
||||
'201': openapi.ResponseSpec{
|
||||
description: 'Pet created'
|
||||
content: {
|
||||
'application/json': openapi.MediaType{
|
||||
schema: Reference{
|
||||
ref: '#/components/schemas/Pet'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
'400': openapi.ResponseSpec{
|
||||
description: 'Invalid input'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
'/pets/{petId}': openapi.PathItem{
|
||||
get: openapi.Operation{
|
||||
summary: 'Get a pet by ID'
|
||||
operation_id: 'getPet'
|
||||
parameters: [
|
||||
openapi.Parameter{
|
||||
name: 'petId'
|
||||
in_: 'path'
|
||||
description: 'ID of the pet to retrieve'
|
||||
required: true
|
||||
schema: Schema{
|
||||
typ: 'integer'
|
||||
format: 'int64'
|
||||
}
|
||||
}
|
||||
]
|
||||
responses: {
|
||||
'200': openapi.ResponseSpec{
|
||||
description: 'A pet'
|
||||
content: {
|
||||
'application/json': openapi.MediaType{
|
||||
schema: Reference{
|
||||
ref: '#/components/schemas/Pet'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
'404': openapi.ResponseSpec{
|
||||
description: 'Pet not found'
|
||||
}
|
||||
}
|
||||
}
|
||||
delete: openapi.Operation{
|
||||
summary: 'Delete a pet by ID'
|
||||
operation_id: 'deletePet'
|
||||
parameters: [
|
||||
openapi.Parameter{
|
||||
name: 'petId'
|
||||
in_: 'path'
|
||||
description: 'ID of the pet to delete'
|
||||
required: true
|
||||
schema: Schema{
|
||||
typ: 'integer'
|
||||
format: 'int64'
|
||||
}
|
||||
}
|
||||
]
|
||||
responses: {
|
||||
'204': openapi.ResponseSpec{
|
||||
description: 'Pet deleted'
|
||||
}
|
||||
'404': openapi.ResponseSpec{
|
||||
description: 'Pet not found'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
'/orders': openapi.PathItem{
|
||||
get: openapi.Operation{
|
||||
summary: 'List all orders'
|
||||
operation_id: 'listOrders'
|
||||
responses: {
|
||||
'200': openapi.ResponseSpec{
|
||||
description: 'A list of orders'
|
||||
content: {
|
||||
'application/json': openapi.MediaType{
|
||||
schema: Schema{
|
||||
typ: 'array'
|
||||
items: SchemaRef(Reference{
|
||||
ref: '#/components/schemas/Order'
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
'/orders/{orderId}': openapi.PathItem{
|
||||
get: openapi.Operation{
|
||||
summary: 'Get an order by ID'
|
||||
operation_id: 'getOrder'
|
||||
parameters: [
|
||||
openapi.Parameter{
|
||||
name: 'orderId'
|
||||
in_: 'path'
|
||||
description: 'ID of the order to retrieve'
|
||||
required: true
|
||||
schema: Schema{
|
||||
typ: 'integer'
|
||||
format: 'int64'
|
||||
}
|
||||
}
|
||||
]
|
||||
responses: {
|
||||
'200': openapi.ResponseSpec{
|
||||
description: 'An order'
|
||||
content: {
|
||||
'application/json': openapi.MediaType{
|
||||
schema: Reference{
|
||||
ref: '#/components/schemas/Order'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
'404': openapi.ResponseSpec{
|
||||
description: 'Order not found'
|
||||
}
|
||||
}
|
||||
}
|
||||
delete: openapi.Operation{
|
||||
summary: 'Delete an order by ID'
|
||||
operation_id: 'deleteOrder'
|
||||
parameters: [
|
||||
openapi.Parameter{
|
||||
name: 'orderId'
|
||||
in_: 'path'
|
||||
description: 'ID of the order to delete'
|
||||
required: true
|
||||
schema: Schema{
|
||||
typ: 'integer'
|
||||
format: 'int64'
|
||||
}
|
||||
}
|
||||
]
|
||||
responses: {
|
||||
'204': openapi.ResponseSpec{
|
||||
description: 'Order deleted'
|
||||
}
|
||||
'404': openapi.ResponseSpec{
|
||||
description: 'Order not found'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
'/users': openapi.PathItem{
|
||||
post: openapi.Operation{
|
||||
summary: 'Create a user'
|
||||
operation_id: 'createUser'
|
||||
request_body: openapi.RequestBody{
|
||||
required: true
|
||||
content: {
|
||||
'application/json': openapi.MediaType{
|
||||
schema: Reference{
|
||||
ref: '#/components/schemas/NewUser'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
responses: {
|
||||
'201': openapi.ResponseSpec{
|
||||
description: 'User created'
|
||||
content: {
|
||||
'application/json': openapi.MediaType{
|
||||
schema: Reference{
|
||||
ref: '#/components/schemas/User'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
components: openapi.Components{
|
||||
schemas: {
|
||||
'Pet': SchemaRef(Schema{
|
||||
typ: 'object'
|
||||
required: ['id', 'name']
|
||||
properties: {
|
||||
'id': SchemaRef(Schema{
|
||||
typ: 'integer'
|
||||
format: 'int64'
|
||||
})
|
||||
'name': SchemaRef(Schema{
|
||||
typ: 'string'
|
||||
})
|
||||
'tag': SchemaRef(Schema{
|
||||
typ: 'string'
|
||||
})
|
||||
}
|
||||
})
|
||||
'NewPet': SchemaRef(Schema{
|
||||
typ: 'object'
|
||||
required: ['name']
|
||||
properties: {
|
||||
'name': SchemaRef(Schema{
|
||||
typ: 'string'
|
||||
})
|
||||
'tag': SchemaRef(Schema{
|
||||
typ: 'string'
|
||||
})
|
||||
}
|
||||
})
|
||||
'Pets': SchemaRef(Schema{
|
||||
typ: 'array'
|
||||
items: SchemaRef(Reference{
|
||||
ref: '#/components/schemas/Pet'
|
||||
})
|
||||
})
|
||||
'Order': SchemaRef(Schema{
|
||||
typ: 'object'
|
||||
required: ['id', 'petId', 'quantity', 'shipDate']
|
||||
properties: {
|
||||
'id': SchemaRef(Schema{
|
||||
typ: 'integer'
|
||||
format: 'int64'
|
||||
})
|
||||
'petId': SchemaRef(Schema{
|
||||
typ: 'integer'
|
||||
format: 'int64'
|
||||
})
|
||||
'quantity': SchemaRef(Schema{
|
||||
typ: 'integer'
|
||||
format: 'int32'
|
||||
})
|
||||
'shipDate': SchemaRef(Schema{
|
||||
typ: 'string'
|
||||
format: 'date-time'
|
||||
})
|
||||
'status': SchemaRef(Schema{
|
||||
typ: 'string'
|
||||
enum_: ['placed', 'approved', 'delivered']
|
||||
})
|
||||
'complete': SchemaRef(Schema{
|
||||
typ: 'boolean'
|
||||
})
|
||||
}
|
||||
})
|
||||
'User': SchemaRef(Schema{
|
||||
typ: 'object'
|
||||
required: ['id', 'username']
|
||||
properties: {
|
||||
'id': SchemaRef(Schema{
|
||||
typ: 'integer'
|
||||
format: 'int64'
|
||||
})
|
||||
'username': SchemaRef(Schema{
|
||||
typ: 'string'
|
||||
})
|
||||
'email': SchemaRef(Schema{
|
||||
typ: 'string'
|
||||
})
|
||||
'phone': SchemaRef(Schema{
|
||||
typ: 'string'
|
||||
})
|
||||
}
|
||||
})
|
||||
'NewUser': SchemaRef(Schema{
|
||||
typ: 'object'
|
||||
required: ['username']
|
||||
properties: {
|
||||
'username': SchemaRef(Schema{
|
||||
typ: 'string'
|
||||
})
|
||||
'email': SchemaRef(Schema{
|
||||
typ: 'string'
|
||||
})
|
||||
'phone': SchemaRef(Schema{
|
||||
typ: 'string'
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const actor_spec = specification.ActorSpecification{
|
||||
name: 'Pet Store API'
|
||||
description: 'A sample API for a pet store'
|
||||
interfaces: [.openapi]
|
||||
const openrpc_spec = openrpc.OpenRPC{
|
||||
openrpc: '1.0.0-rc1'
|
||||
info: openrpc.Info{
|
||||
title: 'Petstore'
|
||||
license: openrpc.License{
|
||||
name: 'MIT'
|
||||
}
|
||||
version: '1.0.0'
|
||||
}
|
||||
servers: [openrpc.Server{
|
||||
name: 'localhost'
|
||||
url: openrpc.RuntimeExpression('http://localhost:8080')
|
||||
}]
|
||||
methods: [
|
||||
specification.ActorMethod{
|
||||
name: 'listPets'
|
||||
openrpc.Method{
|
||||
name: 'list_pets'
|
||||
summary: 'List all pets'
|
||||
parameters: [
|
||||
openrpc.ContentDescriptor{
|
||||
name: 'limit'
|
||||
summary: 'Maximum number of pets to return'
|
||||
description: 'Maximum number of pets to return'
|
||||
schema: jsonschema.SchemaRef(jsonschema.Schema{
|
||||
typ: 'integer'
|
||||
format: 'int32'
|
||||
})
|
||||
}
|
||||
]
|
||||
result: openrpc.ContentDescriptor{
|
||||
name: 'result'
|
||||
description: 'The response of the operation.'
|
||||
schema: jsonschema.SchemaRef(jsonschema.Reference{
|
||||
ref: '#/components/schemas/Pets'
|
||||
params: [openrpc.ContentDescriptorRef(openrpc.ContentDescriptor{
|
||||
name: 'limit'
|
||||
description: 'How many items to return at one time (max 100)'
|
||||
required: false
|
||||
schema: jsonschema.SchemaRef(jsonschema.Schema{
|
||||
typ: 'integer'
|
||||
minimum: 1
|
||||
})
|
||||
}
|
||||
errors: [
|
||||
openrpc.ErrorSpec{
|
||||
code: 400
|
||||
message: 'Invalid request'
|
||||
}
|
||||
]
|
||||
},
|
||||
specification.ActorMethod{
|
||||
name: 'createPet'
|
||||
summary: 'Create a new pet'
|
||||
result: openrpc.ContentDescriptor{
|
||||
name: 'result'
|
||||
description: 'The response of the operation.'
|
||||
}
|
||||
errors: [
|
||||
openrpc.ErrorSpec{
|
||||
code: 400
|
||||
message: 'Invalid input'
|
||||
}
|
||||
]
|
||||
},
|
||||
specification.ActorMethod{
|
||||
name: 'getPet'
|
||||
summary: 'Get a pet by ID'
|
||||
parameters: [
|
||||
openrpc.ContentDescriptor{
|
||||
name: 'petId'
|
||||
summary: 'ID of the pet to retrieve'
|
||||
description: 'ID of the pet to retrieve'
|
||||
schema: jsonschema.SchemaRef(jsonschema.Schema{
|
||||
typ: 'integer'
|
||||
format: 'int64'
|
||||
})
|
||||
}
|
||||
]
|
||||
result: openrpc.ContentDescriptor{
|
||||
name: 'result'
|
||||
description: 'The response of the operation.'
|
||||
schema: jsonschema.SchemaRef(jsonschema.Reference{
|
||||
ref: '#/components/schemas/Pet'
|
||||
})
|
||||
}
|
||||
errors: [
|
||||
openrpc.ErrorSpec{
|
||||
code: 404
|
||||
message: 'Pet not found'
|
||||
}
|
||||
]
|
||||
},
|
||||
specification.ActorMethod{
|
||||
name: 'deletePet'
|
||||
summary: 'Delete a pet by ID'
|
||||
parameters: [
|
||||
openrpc.ContentDescriptor{
|
||||
name: 'petId'
|
||||
summary: 'ID of the pet to delete'
|
||||
description: 'ID of the pet to delete'
|
||||
schema: jsonschema.SchemaRef(jsonschema.Schema{
|
||||
typ: 'integer'
|
||||
format: 'int64'
|
||||
})
|
||||
}
|
||||
]
|
||||
result: openrpc.ContentDescriptor{
|
||||
name: 'result'
|
||||
description: 'The response of the operation.'
|
||||
}
|
||||
errors: [
|
||||
openrpc.ErrorSpec{
|
||||
code: 404
|
||||
message: 'Pet not found'
|
||||
}
|
||||
]
|
||||
},
|
||||
specification.ActorMethod{
|
||||
name: 'listOrders'
|
||||
summary: 'List all orders'
|
||||
result: openrpc.ContentDescriptor{
|
||||
name: 'result'
|
||||
description: 'The response of the operation.'
|
||||
})]
|
||||
result: openrpc.ContentDescriptorRef(openrpc.ContentDescriptor{
|
||||
name: 'pets'
|
||||
description: 'A paged array of pets'
|
||||
schema: jsonschema.SchemaRef(jsonschema.Schema{
|
||||
typ: 'array'
|
||||
items: jsonschema.Items(jsonschema.SchemaRef(jsonschema.Reference{
|
||||
ref: '#/components/schemas/Order'
|
||||
ref: '#/components/schemas/Pet'
|
||||
}))
|
||||
})
|
||||
})
|
||||
examples: [openrpc.ExamplePairing{
|
||||
name: 'listPetExample'
|
||||
description: 'List pet example'
|
||||
}]
|
||||
},
|
||||
openrpc.Method{
|
||||
name: 'create_pet'
|
||||
summary: 'Create a pet'
|
||||
params: [
|
||||
openrpc.ContentDescriptorRef(openrpc.ContentDescriptor{
|
||||
name: 'newPetName'
|
||||
description: 'Name of pet to create'
|
||||
required: true
|
||||
schema: jsonschema.SchemaRef(jsonschema.Schema{
|
||||
typ: 'string'
|
||||
})
|
||||
}),
|
||||
openrpc.ContentDescriptorRef(openrpc.ContentDescriptor{
|
||||
name: 'newPetTag'
|
||||
description: 'Pet tag to create'
|
||||
schema: jsonschema.SchemaRef(jsonschema.Schema{
|
||||
typ: 'string'
|
||||
})
|
||||
})
|
||||
]
|
||||
result: openrpc.ContentDescriptorRef(jsonschema.Reference{
|
||||
ref: '#/components/contentDescriptors/PetId'
|
||||
})
|
||||
examples: [openrpc.ExamplePairing{
|
||||
name: 'createPetExample'
|
||||
description: 'Create pet example'
|
||||
}]
|
||||
},
|
||||
openrpc.Method{
|
||||
name: 'get_pet'
|
||||
summary: 'Info for a specific pet'
|
||||
params: [openrpc.ContentDescriptorRef(jsonschema.Reference{
|
||||
ref: '#/components/contentDescriptors/PetId'
|
||||
})]
|
||||
result: openrpc.ContentDescriptorRef(openrpc.ContentDescriptor{
|
||||
name: 'pet'
|
||||
description: 'Expected response to a valid request'
|
||||
schema: jsonschema.SchemaRef(jsonschema.Reference{
|
||||
ref: '#/components/schemas/Pet'
|
||||
})
|
||||
})
|
||||
examples: [openrpc.ExamplePairing{
|
||||
name: 'getPetExample'
|
||||
description: 'Get pet example'
|
||||
}]
|
||||
},
|
||||
openrpc.Method{
|
||||
name: 'update_pet'
|
||||
summary: 'Update a pet'
|
||||
params: [
|
||||
openrpc.ContentDescriptorRef(jsonschema.Reference{
|
||||
ref: '#/components/contentDescriptors/PetId'
|
||||
}),
|
||||
openrpc.ContentDescriptorRef(openrpc.ContentDescriptor{
|
||||
name: 'updatedPetName'
|
||||
description: 'New name for the pet'
|
||||
required: true
|
||||
schema: jsonschema.SchemaRef(jsonschema.Schema{
|
||||
typ: 'string'
|
||||
})
|
||||
}),
|
||||
openrpc.ContentDescriptorRef(openrpc.ContentDescriptor{
|
||||
name: 'updatedPetTag'
|
||||
description: 'New tag for the pet'
|
||||
schema: jsonschema.SchemaRef(jsonschema.Schema{
|
||||
typ: 'string'
|
||||
})
|
||||
})
|
||||
]
|
||||
result: openrpc.ContentDescriptorRef(openrpc.ContentDescriptor{
|
||||
name: 'pet'
|
||||
description: 'Updated pet object'
|
||||
schema: jsonschema.SchemaRef(jsonschema.Reference{
|
||||
ref: '#/components/schemas/Pet'
|
||||
})
|
||||
})
|
||||
examples: [openrpc.ExamplePairing{
|
||||
name: 'updatePetExample'
|
||||
description: 'Update pet example'
|
||||
}]
|
||||
},
|
||||
openrpc.Method{
|
||||
name: 'delete_pet'
|
||||
summary: 'Delete a pet'
|
||||
params: [openrpc.ContentDescriptorRef(jsonschema.Reference{
|
||||
ref: '#/components/contentDescriptors/PetId'
|
||||
})]
|
||||
result: openrpc.ContentDescriptorRef(openrpc.ContentDescriptor{
|
||||
name: 'success'
|
||||
description: 'Boolean indicating success'
|
||||
schema: jsonschema.SchemaRef(jsonschema.Schema{
|
||||
typ: 'boolean'
|
||||
})
|
||||
})
|
||||
examples: [openrpc.ExamplePairing{
|
||||
name: 'deletePetExample'
|
||||
description: 'Delete pet example'
|
||||
}]
|
||||
}
|
||||
]
|
||||
components: openrpc.Components{
|
||||
content_descriptors: {
|
||||
'PetId': openrpc.ContentDescriptorRef(openrpc.ContentDescriptor{
|
||||
name: 'petId'
|
||||
description: 'The ID of the pet'
|
||||
required: true
|
||||
schema: jsonschema.SchemaRef(jsonschema.Reference{
|
||||
ref: '#/components/schemas/PetId'
|
||||
})
|
||||
})
|
||||
}
|
||||
schemas: {
|
||||
'PetId': jsonschema.SchemaRef(jsonschema.Schema{
|
||||
typ: 'integer'
|
||||
minimum: 0
|
||||
}),
|
||||
'Pet': jsonschema.SchemaRef(jsonschema.Schema{
|
||||
typ: 'object'
|
||||
properties: {
|
||||
'id': jsonschema.SchemaRef(jsonschema.Reference{
|
||||
ref: '#/components/schemas/PetId'
|
||||
}),
|
||||
'name': jsonschema.SchemaRef(jsonschema.Schema{
|
||||
typ: 'string'
|
||||
}),
|
||||
'tag': jsonschema.SchemaRef(jsonschema.Schema{
|
||||
typ: 'string'
|
||||
})
|
||||
}
|
||||
required: ['id', 'name']
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const actor_spec = specification.ActorSpecification{
|
||||
name: 'Petstore'
|
||||
structure: code.Struct{}
|
||||
interfaces: [.openrpc]
|
||||
methods: [
|
||||
specification.ActorMethod{
|
||||
name: 'list_pets'
|
||||
summary: 'List all pets'
|
||||
parameters: [openrpc.ContentDescriptor{
|
||||
name: 'limit'
|
||||
description: 'How many items to return at one time (max 100)'
|
||||
required: false
|
||||
schema: jsonschema.SchemaRef(jsonschema.Schema{
|
||||
typ: 'integer'
|
||||
minimum: 1
|
||||
})
|
||||
}]
|
||||
result: openrpc.ContentDescriptor{
|
||||
name: 'pets'
|
||||
description: 'A paged array of pets'
|
||||
schema: jsonschema.SchemaRef(jsonschema.Schema{
|
||||
typ: 'array'
|
||||
items: jsonschema.Items(jsonschema.SchemaRef(jsonschema.Reference{
|
||||
ref: '#/components/schemas/Pet'
|
||||
}))
|
||||
})
|
||||
}
|
||||
},
|
||||
specification.ActorMethod{
|
||||
name: 'getOrder'
|
||||
summary: 'Get an order by ID'
|
||||
name: 'create_pet'
|
||||
summary: 'Create a pet'
|
||||
parameters: [
|
||||
openrpc.ContentDescriptor{
|
||||
name: 'orderId'
|
||||
summary: 'ID of the order to retrieve'
|
||||
description: 'ID of the order to retrieve'
|
||||
name: 'newPetName'
|
||||
description: 'Name of pet to create'
|
||||
required: true
|
||||
schema: jsonschema.SchemaRef(jsonschema.Schema{
|
||||
typ: 'integer'
|
||||
format: 'int64'
|
||||
typ: 'string'
|
||||
})
|
||||
},
|
||||
openrpc.ContentDescriptor{
|
||||
name: 'newPetTag'
|
||||
description: 'Pet tag to create'
|
||||
schema: jsonschema.SchemaRef(jsonschema.Schema{
|
||||
typ: 'string'
|
||||
})
|
||||
}
|
||||
]
|
||||
result: openrpc.ContentDescriptor{
|
||||
name: 'result'
|
||||
description: 'The response of the operation.'
|
||||
schema: jsonschema.SchemaRef(jsonschema.Reference{
|
||||
ref: '#/components/schemas/Order'
|
||||
name: 'petId'
|
||||
description: 'The ID of the created pet'
|
||||
schema: jsonschema.SchemaRef(jsonschema.Schema{
|
||||
typ: 'integer'
|
||||
})
|
||||
}
|
||||
errors: [
|
||||
openrpc.ErrorSpec{
|
||||
code: 404
|
||||
message: 'Order not found'
|
||||
}
|
||||
]
|
||||
},
|
||||
specification.ActorMethod{
|
||||
name: 'deleteOrder'
|
||||
summary: 'Delete an order by ID'
|
||||
name: 'get_pet'
|
||||
summary: 'Info for a specific pet'
|
||||
parameters: [openrpc.ContentDescriptor{
|
||||
name: 'petId'
|
||||
description: 'The ID of the pet to retrieve'
|
||||
required: true
|
||||
schema: jsonschema.SchemaRef(jsonschema.Reference{
|
||||
ref: '#/components/schemas/PetId'
|
||||
})
|
||||
}]
|
||||
result: openrpc.ContentDescriptor{
|
||||
name: 'pet'
|
||||
description: 'The pet details'
|
||||
schema: jsonschema.SchemaRef(jsonschema.Reference{
|
||||
ref: '#/components/schemas/Pet'
|
||||
})
|
||||
}
|
||||
},
|
||||
specification.ActorMethod{
|
||||
name: 'update_pet'
|
||||
summary: 'Update a pet'
|
||||
parameters: [
|
||||
openrpc.ContentDescriptor{
|
||||
name: 'orderId'
|
||||
summary: 'ID of the order to delete'
|
||||
description: 'ID of the order to delete'
|
||||
name: 'petId'
|
||||
description: 'The ID of the pet to update'
|
||||
required: true
|
||||
schema: jsonschema.SchemaRef(jsonschema.Reference{
|
||||
ref: '#/components/schemas/PetId'
|
||||
})
|
||||
},
|
||||
openrpc.ContentDescriptor{
|
||||
name: 'updatedPetName'
|
||||
description: 'New name for the pet'
|
||||
schema: jsonschema.SchemaRef(jsonschema.Schema{
|
||||
typ: 'integer'
|
||||
format: 'int64'
|
||||
typ: 'string'
|
||||
})
|
||||
},
|
||||
openrpc.ContentDescriptor{
|
||||
name: 'updatedPetTag'
|
||||
description: 'New tag for the pet'
|
||||
schema: jsonschema.SchemaRef(jsonschema.Schema{
|
||||
typ: 'string'
|
||||
})
|
||||
}
|
||||
]
|
||||
result: openrpc.ContentDescriptor{
|
||||
name: 'result'
|
||||
description: 'The response of the operation.'
|
||||
name: 'pet'
|
||||
description: 'The updated pet object'
|
||||
schema: jsonschema.SchemaRef(jsonschema.Reference{
|
||||
ref: '#/components/schemas/Pet'
|
||||
})
|
||||
}
|
||||
errors: [
|
||||
openrpc.ErrorSpec{
|
||||
code: 404
|
||||
message: 'Order not found'
|
||||
}
|
||||
]
|
||||
},
|
||||
specification.ActorMethod{
|
||||
name: 'createUser'
|
||||
summary: 'Create a user'
|
||||
name: 'delete_pet'
|
||||
summary: 'Delete a pet'
|
||||
parameters: [openrpc.ContentDescriptor{
|
||||
name: 'petId'
|
||||
description: 'The ID of the pet to delete'
|
||||
required: true
|
||||
schema: jsonschema.SchemaRef(jsonschema.Reference{
|
||||
ref: '#/components/schemas/PetId'
|
||||
})
|
||||
}]
|
||||
result: openrpc.ContentDescriptor{
|
||||
name: 'result'
|
||||
description: 'The response of the operation.'
|
||||
}
|
||||
}
|
||||
]
|
||||
objects: [
|
||||
specification.BaseObject{
|
||||
structure: code.Struct{
|
||||
name: 'Pet'
|
||||
}
|
||||
},
|
||||
specification.BaseObject{
|
||||
structure: code.Struct{
|
||||
name: 'NewPet'
|
||||
}
|
||||
},
|
||||
specification.BaseObject{
|
||||
structure: code.Struct{
|
||||
name: 'Pets'
|
||||
}
|
||||
},
|
||||
specification.BaseObject{
|
||||
structure: code.Struct{
|
||||
name: 'Order'
|
||||
}
|
||||
},
|
||||
specification.BaseObject{
|
||||
structure: code.Struct{
|
||||
name: 'User'
|
||||
}
|
||||
},
|
||||
specification.BaseObject{
|
||||
structure: code.Struct{
|
||||
name: 'NewUser'
|
||||
name: 'success'
|
||||
description: 'Boolean indicating success'
|
||||
schema: jsonschema.SchemaRef(jsonschema.Schema{
|
||||
typ: 'boolean'
|
||||
})
|
||||
}
|
||||
}
|
||||
]
|
||||
objects: []
|
||||
}
|
||||
|
||||
pub fn test_from_openapi() ! {
|
||||
assert from_openapi(openapi_spec)! == actor_spec
|
||||
pub fn test_from_openrpc() ! {
|
||||
panic(from_openrpc(openrpc_spec)!)
|
||||
assert from_openrpc(openrpc_spec)! == actor_spec
|
||||
}
|
||||
@@ -2,6 +2,7 @@ module specification
|
||||
|
||||
import freeflowuniverse.herolib.core.code { Struct, Function }
|
||||
import freeflowuniverse.herolib.schemas.openrpc {ContentDescriptor, ErrorSpec}
|
||||
import freeflowuniverse.herolib.schemas.jsonschema {Schema}
|
||||
|
||||
pub struct ActorSpecification {
|
||||
pub mut:
|
||||
@@ -33,7 +34,5 @@ pub:
|
||||
|
||||
pub struct BaseObject {
|
||||
pub:
|
||||
structure Struct @[omitempty]
|
||||
methods []Function @[omitempty]
|
||||
children []Struct @[omitempty]
|
||||
schema Schema
|
||||
}
|
||||
@@ -33,7 +33,7 @@ pub fn (s ActorSpecification) to_openapi() OpenAPI {
|
||||
|
||||
mut schemas := map[string]SchemaRef{}
|
||||
for object in s.objects {
|
||||
schemas[object.structure.name] = object.to_schema()
|
||||
schemas[object.schema.id] = object.to_schema()
|
||||
}
|
||||
|
||||
return OpenAPI{
|
||||
|
||||
@@ -43,10 +43,10 @@ import freeflowuniverse.herolib.schemas.jsonschema.codegen { struct_to_schema }
|
||||
pub fn (specification ActorSpecification) to_openrpc() OpenRPC {
|
||||
mut schemas := map[string]SchemaRef{}
|
||||
for obj in specification.objects {
|
||||
schemas[obj.structure.name] = struct_to_schema(obj.structure)
|
||||
for child in obj.children {
|
||||
schemas[child.name] = struct_to_schema(child)
|
||||
}
|
||||
schemas[obj.schema.id] = obj.schema
|
||||
// for child in obj.children {
|
||||
// schemas[child.name] = struct_to_schema(child)
|
||||
// }
|
||||
}
|
||||
return OpenRPC{
|
||||
info: openrpc.Info{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
module jsonschema
|
||||
|
||||
type Items = SchemaRef | []SchemaRef
|
||||
pub type Items = SchemaRef | []SchemaRef
|
||||
|
||||
pub type SchemaRef = Reference | Schema
|
||||
|
||||
|
||||
@@ -12,7 +12,6 @@ fn test_decode() ! {
|
||||
mut doc_file := pathlib.get_file(path: openrpc.doc_path)!
|
||||
content := doc_file.read()!
|
||||
object := decode(content)!
|
||||
|
||||
assert object.openrpc == '1.0.0-rc1'
|
||||
assert object.methods.map(it.name) == ['list_pets', 'create_pet', 'get_pet']
|
||||
}
|
||||
|
||||
48
lib/schemas/openrpc/inflate.v
Normal file
48
lib/schemas/openrpc/inflate.v
Normal file
@@ -0,0 +1,48 @@
|
||||
module openrpc
|
||||
|
||||
import freeflowuniverse.herolib.schemas.jsonschema {Schema, Reference, SchemaRef, Items}
|
||||
|
||||
pub fn (s OpenRPC) inflate_method(method Method) Method {
|
||||
return Method {
|
||||
...method,
|
||||
params: method.params.map(ContentDescriptorRef(s.inflate_content_descriptor(it)))
|
||||
result: s.inflate_content_descriptor(method.result)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (s OpenRPC) inflate_content_descriptor(cd_ ContentDescriptorRef) ContentDescriptor {
|
||||
cd := if cd_ is Reference {
|
||||
s.components.content_descriptors[cd_.ref] as ContentDescriptor
|
||||
} else { cd_ as ContentDescriptor }
|
||||
|
||||
return ContentDescriptor {
|
||||
...cd,
|
||||
schema: s.inflate_schema(cd.schema)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (s OpenRPC) inflate_schema(schema_ref SchemaRef) Schema {
|
||||
if typeof(schema_ref).starts_with('unknown') { return Schema{}}
|
||||
schema := if schema_ref is Reference {
|
||||
if schema_ref.ref == '' {return Schema{}}
|
||||
if !schema_ref.ref.starts_with('#/components/schemas/') {
|
||||
panic('not implemented')
|
||||
}
|
||||
schema_name := schema_ref.ref.trim_string_left('#/components/schemas/')
|
||||
s.inflate_schema(s.components.schemas[schema_name])
|
||||
} else { schema_ref as Schema}
|
||||
|
||||
return Schema {
|
||||
...schema,
|
||||
items: s.inflate_items(schema.items)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (s OpenRPC) inflate_items(items Items) Items {
|
||||
return if items is []SchemaRef {
|
||||
Items(items.map(SchemaRef(s.inflate_schema(it))))
|
||||
} else {
|
||||
its := Items(SchemaRef(s.inflate_schema(items as SchemaRef)))
|
||||
return its
|
||||
}
|
||||
}
|
||||
@@ -29,6 +29,7 @@ pub:
|
||||
|
||||
// Contact information for the exposed API.
|
||||
pub struct Contact {
|
||||
pub:
|
||||
name string @[omitempty] // The identifying name of the contact person/organization.
|
||||
email string @[omitempty] // The URL pointing to the contact information. MUST be in the format of a URL.
|
||||
url string @[omitempty] // The email address of the contact person/organization. MUST be in the format of an email address.
|
||||
@@ -36,6 +37,7 @@ pub struct Contact {
|
||||
|
||||
// License information for the exposed API.
|
||||
pub struct License {
|
||||
pub:
|
||||
name string @[omitempty] // The license name used for the API.
|
||||
url string @[omitempty] // A URL to the license used for the API. MUST be in the format of a URL.
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user