class SlackResources::Generator::ToSchema

Public Class Methods

new(example:, url:, preset:, key: 'root', defined: {}, defined_used: Set.new, parent: {}, root: nil) click to toggle source
# File lib/slack_resources/generator/event_api/to_schema.rb, line 10
def initialize(example:, url:, preset:, key: 'root', defined: {}, defined_used: Set.new, parent: {}, root: nil)
  @example = JSON.parse(example.to_json).key_ordered
  @url = url
  @preset = preset
  @key = key
  @defined = defined
  @defined_used = defined_used
  @parent = parent
  @root = root || @example
end

Public Instance Methods

array_type?(type) click to toggle source
# File lib/slack_resources/generator/event_api/to_schema.rb, line 72
def array_type?(type)
  type.to_s[0..1] == '[]'
end
define_as_array(array_type, values) click to toggle source
# File lib/slack_resources/generator/event_api/to_schema.rb, line 80
def define_as_array(array_type, values)
  type = array_type[2..-1]

  if TypeDetection.default_type?(type)
    return {
      'type' => 'array',
      'items' => {
        'type' => type,
      },
    }
  end

  if values.first.is_a?(Hash)
    to_child_schema(
      prop_name: type,
      example: values.first,
      key: type,
      parent: @example
    )
  elsif values.first.is_a?(String)
    define_string(type)
  end

  {
    'type' => 'array',
    'items' => ref_to(type),
  }
end
define_default_type(prop_name, value, container, const = false) click to toggle source
# File lib/slack_resources/generator/event_api/to_schema.rb, line 147
def define_default_type(prop_name, value, container, const = false)
  @defined.protect_merge!(
    prop_name => {
      'type' => detect_default_type(prop_name, value, container, const),
    }
  )
  @defined_used << prop_name

  ref_to(prop_name)
end
define_object(k, v, types) click to toggle source
# File lib/slack_resources/generator/event_api/to_schema.rb, line 109
def define_object(k, v, types)
  ref_key = k == 'item' ? "#{root_type_prefix}_item" : k

  to_child_schema(
    prop_name: ref_key,
    example: v,
    key: k,
    parent: types
  )

  ref_key
end
define_special_type(prop_name, value, container, const) click to toggle source
# File lib/slack_resources/generator/event_api/to_schema.rb, line 122
def define_special_type(prop_name, value, container, const)
  @defined_used << prop_name

  return prop_name if @parent[prop_name]

  types = value['items'].map { |v| detect_default_type(prop_name, v, container) }.uniq

  @defined[prop_name] =
    if const
      { 'type' => normalize_type(types), enum: value['items'].uniq }
    else
      { 'type' => normalize_type(types) }
    end

  prop_name
end
define_string(prop_name) click to toggle source
# File lib/slack_resources/generator/event_api/to_schema.rb, line 143
def define_string(prop_name)
  define_default_type(prop_name, 'string', nil)
end
detail?(type) click to toggle source
# File lib/slack_resources/generator/event_api/to_schema.rb, line 76
def detail?(type)
  type.is_a?(Hash)
end
detect_default_type(prop_name, value, container, const = false) click to toggle source
# File lib/slack_resources/generator/event_api/to_schema.rb, line 158
def detect_default_type(prop_name, value, container, const = false)
  return define_special_type(prop_name, value, container, const) if value.is_a?(Hash) && value[TypeDetection::SPECIAL_TYPE] == TypeDetection::MULTIPLE_EXAMPLES

  case value
  when Integer
    'number'
  when Array
    'array'
  when Hash
    define_object(prop_name, value, container)
  when true, false
    'boolean'
  when nil
    'null'
  else
    'string'
  end
end
execute!() click to toggle source
# File lib/slack_resources/generator/event_api/to_schema.rb, line 21
def execute!
  properties = @example.inject({}) do |a, (prop_name, value)|
    type = TypeDetection.new(
      parent_key: @key,
      to_schema_instance: self,
      prop_name: prop_name,
      value: value,
      container: @example,
      preset: @preset
    ).execute!

    @defined_used << type if type.is_a?(String)

    definition =
      case
      when TypeDetection.default_type?(type)
        { 'type' => type }
      when detail?(type)
        type
      when array_type?(type)
        define_as_array(type, value)
      else
        ref_to(type)
      end

    a.merge(prop_name => definition)
  end

  [
    {
      'type' => 'object',
      'description' => properties.blank? ? "definition snipped. learn more: #{@url}" : '(defined by script)',
      'properties' => properties,
    },
    @defined,
    @defined_used,
  ]
end
normalize_type(types) click to toggle source
# File lib/slack_resources/generator/event_api/to_schema.rb, line 139
def normalize_type(types)
  types.size == 1 ? types[0] : types
end
ref_to(type) click to toggle source
# File lib/slack_resources/generator/event_api/to_schema.rb, line 177
def ref_to(type)
  { '$ref' => "#/definitions/#{type}" }
end
root_schema?() click to toggle source
# File lib/slack_resources/generator/event_api/to_schema.rb, line 60
def root_schema?
  @root == @example
end
root_type() click to toggle source
# File lib/slack_resources/generator/event_api/to_schema.rb, line 64
def root_type
  @root['type']
end
root_type_prefix() click to toggle source
# File lib/slack_resources/generator/event_api/to_schema.rb, line 68
def root_type_prefix
  @root_type_prefix ||= root_type.split('_').shift
end
to_child_schema(params) click to toggle source
# File lib/slack_resources/generator/event_api/to_schema.rb, line 181
def to_child_schema(params)
  prop_name = params.delete(:prop_name)
  SlackResources::Generator::ToSchema.new(
    example: @example,
    url: @url,
    preset: @preset,
    key: @key,
    defined: @defined,
    defined_used: @defined_used,
    parent: @parent,
    root: @root,
    **params
  ).execute!.tap do |schema,|
    @defined_used << prop_name
    @defined[prop_name] = schema
  end
end