diff --git a/examples/config.ru b/examples/config.ru index b24eed8..af91442 100644 --- a/examples/config.ru +++ b/examples/config.ru @@ -9,7 +9,7 @@ require 'core_api/base' require 'apia-openapi' -use Apia::OpenAPI::Rack, 'CoreAPI::Base', '/core/v1/schema/openapi.json' +use Apia::OpenAPI::Rack, 'CoreAPI::Base', '/core/v1/schema/openapi.json', base_url: 'http://127.0.0.1:9292/core/v1/' use Apia::Rack, CoreAPI::Base, '/core/v1', development: true app = proc do diff --git a/examples/core_api/objects/month_polymorph.rb b/examples/core_api/objects/month_polymorph.rb index 10a33e9..2640de1 100644 --- a/examples/core_api/objects/month_polymorph.rb +++ b/examples/core_api/objects/month_polymorph.rb @@ -7,8 +7,8 @@ module CoreAPI module Objects class MonthPolymorph < Apia::Polymorph - option 'MonthLong', type: CoreAPI::Objects::MonthLong, matcher: proc { |time| time.seconds.even? } - option 'MonthShort', type: CoreAPI::Objects::MonthShort, matcher: proc { |time| time.seconds.odd? } + option 'MonthLong', type: CoreAPI::Objects::MonthLong, matcher: proc { |time| time.sec.even? } + option 'MonthShort', type: CoreAPI::Objects::MonthShort, matcher: proc { |time| time.sec.odd? } end end diff --git a/examples/core_api/objects/time.rb b/examples/core_api/objects/time.rb index 2e2177a..17ebee7 100644 --- a/examples/core_api/objects/time.rb +++ b/examples/core_api/objects/time.rb @@ -11,7 +11,7 @@ class Time < Apia::Object description 'Represents a time' field :unix, type: :unix_time do - backend(&:to_i) + backend { |t| t } end field :day_of_week, type: Objects::Day do @@ -31,13 +31,21 @@ class Time < Apia::Object end field :as_array, type: [:integer] do - backend { |t| [t.year, t.month, t.day, t.hour, t.minute, t.second] } + backend { |t| [t.year, t.month, t.day, t.hour, t.min, t.sec] } end field :as_array_of_objects, type: [Objects::Year] do backend { |t| [t.year] } end + field :as_decimal, type: :decimal do + backend { |t| t.to_f } + end + + field :as_base64, type: :base64 do + backend { |t| Base64.encode64(t.to_s) } + end + end end end diff --git a/lib/apia-openapi/schema.rb b/lib/apia-openapi/schema.rb index 711aa5a..8689c5b 100644 --- a/lib/apia-openapi/schema.rb +++ b/lib/apia-openapi/schema.rb @@ -8,7 +8,7 @@ def initialize(api, base_url) @api = api @base_url = base_url # TODO: should we support multiple urls? @spec = { - openapi: '3.0.0', # swagger-editor does not support 3.1.0 :( + openapi: '3.1.0', info: {}, servers: [], paths: {}, @@ -76,7 +76,7 @@ def add_parameters(route, route_spec) name: "#{arg.name.to_s}[#{child_arg.name.to_s}]", in: "query", schema: { - type: child_arg.type.klass.definition.name.downcase + type: convert_type_to_openapi_data_type(child_arg.type) } } route_spec[:parameters] << param @@ -86,7 +86,7 @@ def add_parameters(route, route_spec) items = { "$ref": "#/components/schemas/#{generate_id(arg.type.klass.definition)}" } add_component_schema(arg) else - items = { type: arg.type.klass.definition.name.downcase } + items = { type: convert_type_to_openapi_data_type(arg.type) } end param = { @@ -113,7 +113,7 @@ def add_parameters(route, route_spec) name: arg.name.to_s, in: "query", schema: { - type: arg.type.klass.definition.name.downcase # TODO: do these map to OpenAPI types? + type: convert_type_to_openapi_data_type(arg.type) } } route_spec[:parameters] << param @@ -154,7 +154,7 @@ def generate_schema(definition:, schema: ,endpoint: nil, path: nil) children = definition.type.klass.definition.fields.values end else - items = { type: definition.type.klass.definition.name.downcase } + items = { type: convert_type_to_openapi_data_type(definition.type) } end if items @@ -176,7 +176,14 @@ def generate_schema(definition:, schema: ,endpoint: nil, path: nil) children = [] end - all_properties_included = definition.type.enum? || endpoint.nil? || children.all? { |child| endpoint.include_field?(path + [child.name]) } + # if !definition.type.enum? && !endpoint.nil? + # puts "definition.type #{definition.type.klass}" + # puts "children: #{children.map { |c| [c.name, endpoint.include_field?(path + [c.name])] }}" + # puts "children.all? #{children.all? { |child| endpoint.include_field?(path + [child.name]) }}" + # puts "" + # end + all_properties_included = definition.type.enum? || endpoint.nil? #|| children.all? { |child| endpoint.include_field?(path + [child.name]) } + #puts "all_properties_included: #{all_properties_included}" children.each do |child| next unless endpoint.nil? || (!definition.type.enum? && endpoint.include_field?(path + [child.name])) @@ -203,7 +210,6 @@ def generate_schema(definition:, schema: ,endpoint: nil, path: nil) add_component_schema(child) else child_path = path.nil? ? nil : path + [child] - puts "definition.type: #{definition.type.inspect}" child_schema = {} schema[:properties][child.name.to_s] = child_schema generate_schema(definition: child, schema: child_schema, endpoint: endpoint, path: child_path) @@ -212,7 +218,7 @@ def generate_schema(definition:, schema: ,endpoint: nil, path: nil) schema[:type] = 'object' schema[:properties] ||= {} schema[:properties][child.name.to_s] = { - type: map_type_to_openapi_property_type(child.type) + type: convert_type_to_openapi_data_type(child.type) } end @@ -231,7 +237,7 @@ def add_request_body(route, route_spec) items = { "$ref": "#/components/schemas/#{id}" } add_component_schema(arg) else - items = { type: arg.type.klass.definition.name.downcase } + items = { type: convert_type_to_openapi_data_type(arg.type) } end properties[arg.name.to_s] = { @@ -245,7 +251,7 @@ def add_request_body(route, route_spec) add_component_schema(arg) else # scalar properties[arg.name.to_s] = { - type: arg.type.klass.definition.name.downcase + type: convert_type_to_openapi_data_type(arg.type) } end @@ -281,7 +287,7 @@ def add_responses(route, route_spec) route_spec[:responses] = { "#{route.endpoint.definition.http_status}": { - description: route.endpoint.definition.description, # does this break if nil? + description: route.endpoint.definition.description || "", content: { "application/json": { schema: schema @@ -320,7 +326,7 @@ def generate_properties_for_response(name, field, endpoint) end end else - items = { type: field.type.klass.definition.name.downcase } + items = { type: convert_type_to_openapi_data_type(field.type) } end if items properties[name] = { @@ -341,7 +347,7 @@ def generate_properties_for_response(name, field, endpoint) end else # scalar properties[name] = { - type: map_type_to_openapi_property_type(field.type) + type: convert_type_to_openapi_data_type(field.type) } end properties @@ -368,11 +374,13 @@ def generate_id(definition) definition.id.gsub(/\//, '_') end - def map_type_to_openapi_property_type(type) + def convert_type_to_openapi_data_type(type) if type.klass == Apia::Scalars::UnixTime 'integer' elsif type.klass == Apia::Scalars::Decimal - 'string' # TODO: or integer, add this to example app + 'number' + elsif type.klass == Apia::Scalars::Base64 + 'string' else type.klass.definition.name.downcase end