Class: Randrizer::Drivers::JSONSchema::Typegen

Inherits:
Object
  • Object
show all
Defined in:
lib/randrizer/drivers/json_schema/typegen.rb

Constant Summary collapse

MONTH_INT_TYPE =
Types::OneOf[(1..12).map { |i| Types::Const.build(i.to_s.rjust(2, "0")) }]
DAY_INT_TYPE =
Types::OneOf[(1..31).map { |i| Types::Const.build(i.to_s.rjust(2, "0")) }]
HOUR_INT_TYPE =
Types::OneOf[(0..23).map { |i| Types::Const.build(i.to_s.rjust(2, "0")) }]
MIN_SEC_INT_TYPE =
Types::OneOf[(0..59).map { |i| Types::Const.build(i.to_s.rjust(2, "0")) }]
DATE_SEQUENCE =
[
  Types::Int.build(min: 1970, max: 2200),
  Types::Const["-"],
  MONTH_INT_TYPE,
  Types::Const["-"],
  DAY_INT_TYPE
].freeze
TIMEZONE_SEQUENCE =
Types::OneOf.build([
  Types::Const["Z"],
  Types::StringSequence.build([
    Types::OneOf.build([Types::Const["+"], Types::Const["-"]]),
    HOUR_INT_TYPE,
    Types::Const[":"],
    MIN_SEC_INT_TYPE
  ])
])
TIME_SEQUENCE =
[
  HOUR_INT_TYPE,
  Types::Const[":"],
  MIN_SEC_INT_TYPE,
  Types::Const[":"],
  MIN_SEC_INT_TYPE,
  Types::Optional.build(inner_type: TIMEZONE_SEQUENCE)
].freeze
EMAIL_SEQUENCE =
[
  Types::String.build(valid_chars: Types::String::CHARS_ALL_LETTERS + "._+"),
  Types::Const["@"],
  Types::String.build(valid_chars: Types::String::CHARS_ALL_LETTERS + "._")
].freeze

Class Method Summary collapse

Class Method Details

.t_boolean(_attrs) ⇒ Object



58
59
60
# File 'lib/randrizer/drivers/json_schema/typegen.rb', line 58

def t_boolean(_attrs)
  Types::Bool[]
end

.t_integer(attrs) ⇒ Object



75
76
77
# File 'lib/randrizer/drivers/json_schema/typegen.rb', line 75

def t_integer(attrs)
  t_number(attrs)
end

.t_null(_attrs) ⇒ Object



52
53
54
55
56
# File 'lib/randrizer/drivers/json_schema/typegen.rb', line 52

def t_null(_attrs)
  # `Types::Nullable` would require an inner type, as this will never change
  # we can just return a constant null value.
  Types::Const[nil]
end

.t_number(attrs) ⇒ Object



62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/randrizer/drivers/json_schema/typegen.rb', line 62

def t_number(attrs)
  # TODO: support multipleOf

  restrictions = {}
  restrictions[:min] = attrs.fetch("minimum", -999_999_999)
  restrictions[:max] = attrs.fetch("maximum", 999_999_999)

  restrictions[:min] += 1 if attrs.fetch("exclusiveMinimum", false)
  restrictions[:max] -= 1 if attrs.fetch("exclusiveMaximum", false)

  Types::Int.build(**restrictions)
end

.t_string(attrs) ⇒ Object



100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
# File 'lib/randrizer/drivers/json_schema/typegen.rb', line 100

def t_string(attrs)
  # TODO: support String patterns format specs

  if attrs.include?("enum")
    return Types::OneOf[
      attrs["enum"].map { |e| Types::Const[e] }
    ]
  end

  if attrs.include?("format")
    return t_string_with_format(attrs, attrs["format"])
  end

  props = {}
  props[:min_length] = attrs["minLength"].to_i if attrs.include?("minLength")
  props[:max_length] = attrs["maxLength"].to_i if attrs.include?("maxLength")

  Types::String.build(**props)
end

.t_string_with_format(_attrs, format) ⇒ Object



79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
# File 'lib/randrizer/drivers/json_schema/typegen.rb', line 79

def t_string_with_format(_attrs, format)
  # https://json-schema.org/understanding-json-schema/reference/string.html#built-in-formats

  case format
  when "date"
    Types::StringSequence.build(DATE_SEQUENCE)
  when "time"
    Types::StringSequence.build(TIME_SEQUENCE)
  when "date-time"
    Types::StringSequence.build([
      DATE_SEQUENCE,
      Types::Const["T"],
      TIME_SEQUENCE
    ].flatten)
  when "email"
    Types::StringSequence.build(EMAIL_SEQUENCE)
  else
    raise "Format not supported: #{format}"
  end
end