explicit 0.2.7 → 0.2.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b817ec6fe610ab86d5938a0b7958633f4f34e68a4d02b9bd8c8a50bf831622bc
4
- data.tar.gz: 8cb2aae4e5a1d582734b6e1f4a917f0b07b4cf4839932dd1e2a5754f3320663b
3
+ metadata.gz: dd88a349ccfac424582d31d9d4f325f5ff03ede07eee06204938643b836310a5
4
+ data.tar.gz: 31c41a8b16b54c1d3e337cc7fb1458af43d24a97123e5f9d68470daf7b90c6dd
5
5
  SHA512:
6
- metadata.gz: 1e385f89b47ec351fb000f5b9097d5ccf6233ac01dd57b9e07e87ac9488718528655ef7033686dc482dd9fc9812063f64c1f79313492157dd3ecad63055ff01b
7
- data.tar.gz: 5fefc99c8c881d334364102f17e9cab4247bf0486dd5744e041654e83354e2b0265dbfaf2f41f185b354370356c33823c036b13fc2010db459e998ae0ba436ef
6
+ metadata.gz: c58b39e3709dbc6edba831aa1c746eb919c0c059ca2c386ac9840ff7ed101b9b0b7342e1e6885b368c3456e23b17e31fc54c8608b2d33efeacdfc3d41895ef55
7
+ data.tar.gz: 8e6b2055a6c55db8192a9ff5fd60773bfad06d1acc136b5056eb037ae3b76593f1d6b594c44c3c7ac63c13bb7f1a2d38a37c09cd670b40c0dd50c775595e0015
data/README.md CHANGED
@@ -28,6 +28,7 @@ documented types at runtime.
28
28
  - [Description](#description)
29
29
  - [Enum](#enum)
30
30
  - [File](#file)
31
+ - [Float](#float)
31
32
  - [Hash](#hash)
32
33
  - [Integer](#integer)
33
34
  - [Literal](#literal)
@@ -141,6 +142,9 @@ request instead of `Explicit::Request`. For example:
141
142
 
142
143
  ```ruby
143
144
  AuthenticatedRequest = Explicit::Request.new do
145
+ base_url "https://my-app.com"
146
+ base_path "/api/v1"
147
+
144
148
  header "Authorization", [:string, format: /Bearer [a-zA-Z0-9]{20}/]
145
149
 
146
150
  response 403, { error: "unauthorized" }
@@ -550,6 +554,18 @@ match value_type. If you are expecting a hash with a specific set of keys use a
550
554
 
551
555
  Value must be an uploaded file using "multipart/form-data" encoding.
552
556
 
557
+ ### Float
558
+
559
+ ```ruby
560
+ :float
561
+ [:float, negative: false]
562
+ [:float, positive: false]
563
+ [:float, min: 0] # inclusive
564
+ [:float, max: 10] # inclusive
565
+ ```
566
+
567
+ Float encoded string alues such as "0.5" or "500.01" are automatically converted to `Float`.
568
+
553
569
  ### Integer
554
570
 
555
571
  ```ruby
@@ -561,7 +577,7 @@ Value must be an uploaded file using "multipart/form-data" encoding.
561
577
  ```
562
578
 
563
579
  Integer encoded string values such as "10" or "-2" are automatically converted
564
- to integer.
580
+ to `Integer`.
565
581
 
566
582
  ### Literal
567
583
 
@@ -2,6 +2,7 @@
2
2
  <html>
3
3
  <head>
4
4
  <title><%= page_title || "API Documentation" %></title>
5
+ <meta charset="UTF-8">
5
6
 
6
7
  <% if favicon_url %>
7
8
  <link rel="icon" href="<%= favicon_url %>" />
@@ -50,7 +51,7 @@
50
51
  Version <%= version %>
51
52
  </div>
52
53
  <div class="p-1 w-1/2">
53
- <%= link_to url_helpers.explicit_documentation_swagger_path, target: "_blank", class: "flex items-center justify-center gap-1 text-neutral-900" do %>
54
+ <%= link_to "https://petstore.swagger.io/?url=#{url_helpers.explicit_documentation_swagger_url(host: request.host)}", target: "_blank", class: "flex items-center justify-center gap-1 text-neutral-900" do %>
54
55
  <span>Swagger</span>
55
56
 
56
57
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="currentColor" class="size-4">
@@ -0,0 +1,25 @@
1
+ <%= type_constraints do %>
2
+ <% if type.min.present? %>
3
+ <%= type_constraint "min", type.min %>
4
+ <% end %>
5
+
6
+ <% if type.max.present? %>
7
+ <%= type_constraint "max", type.max %>
8
+ <% end %>
9
+
10
+ <% if type.negative == false %>
11
+ <%= type_constraint "not", "negative" %>
12
+ <% end %>
13
+
14
+ <% if type.negative == true %>
15
+ <%= type_constraint "only", "negative" %>
16
+ <% end %>
17
+
18
+ <% if type.positive == false %>
19
+ <%= type_constraint "not", "positive" %>
20
+ <% end %>
21
+
22
+ <% if type.positive == true %>
23
+ <%= type_constraint "only", "positive" %>
24
+ <% end %>
25
+ <% end %>
@@ -34,11 +34,14 @@ en:
34
34
  file: "must be a file"
35
35
  file_max_size: "must be smaller than %{max_size}"
36
36
  file_content_type: "file content type must be one of: %{allowed_content_types}"
37
+ float: "must be a number"
37
38
  integer: "must be an integer"
38
39
  min: "must be at least %{min}"
39
40
  max: "must be at most %{max}"
40
41
  not_negative: "must not be negative"
42
+ only_negative: "must be negative"
41
43
  not_positive: "must not be positive"
44
+ only_positive: "must be positive"
42
45
  literal: "must be %{value}"
43
46
  one_of_separator: "OR"
44
47
  string: "must be a string"
@@ -61,9 +64,9 @@ en:
61
64
  file_max_size: "* Max size: %{max_size}"
62
65
  file_content_types: "* Content types: %{content_types}"
63
66
  hash_not_empty: "* Must have at least one value"
64
- integer_not_positive: "* Must not be positive"
65
- integer_only_positive: "* Must be positive"
66
- integer_not_negative: "* Must not be negative"
67
- integer_only_negative: "* Must be negative"
67
+ number_not_positive: "* Must not be positive"
68
+ number_only_positive: "* Must be positive"
69
+ number_not_negative: "* Must not be negative"
70
+ number_only_negative: "* Must be negative"
68
71
  string_not_empty: "* Must not be empty"
69
72
  string_downcase: "* Case insensitive"
@@ -12,6 +12,20 @@ module Explicit::Documentation::Output
12
12
  end
13
13
 
14
14
  def swagger_document
15
+ paths = build_paths_from_requests
16
+
17
+ securitySchemes = {}.tap do |hash|
18
+ requests = paths.flat_map { |path, methods| methods.values }
19
+
20
+ if requests.filter { _1.dig(:security, 0, :basicAuth) }.any?
21
+ hash[:basicAuth] = { type: "http", scheme: "basic" }
22
+ end
23
+
24
+ if requests.filter { _1.dig(:security, 0, :bearerAuth) }.any?
25
+ hash[:bearerAuth] = { type: "http", scheme: "bearer" }
26
+ end
27
+ end
28
+
15
29
  {
16
30
  openapi: "3.0.1",
17
31
  info: {
@@ -24,14 +38,15 @@ module Explicit::Documentation::Output
24
38
  }
25
39
  ],
26
40
  tags: build_tags_from_sections,
27
- paths: build_paths_from_requests
41
+ paths: build_paths_from_requests,
42
+ components: { securitySchemes: }
28
43
  }
29
44
  end
30
45
 
31
46
  def call(request)
32
47
  @swagger_document ||= swagger_document
33
48
 
34
- [200, {"Content-Type" => "application/json"}, [@swagger_document.to_json]]
49
+ [ 200, { "Content-Type" => "application/json" }, [ @swagger_document.to_json ] ]
35
50
  end
36
51
 
37
52
  def inspect
@@ -43,7 +58,7 @@ module Explicit::Documentation::Output
43
58
  base_urls = builder.requests.map(&:get_base_url).uniq
44
59
  base_paths = builder.requests.map(&:get_base_path).uniq
45
60
 
46
- if !base_urls.one?
61
+ if !base_urls.compact_blank.empty? && !base_urls.one?
47
62
  raise InconsistentBaseURLError.new <<~TXT
48
63
  There are requests with different base URLs in the same documentation,
49
64
  which is not supported by Swagger.
@@ -56,7 +71,7 @@ module Explicit::Documentation::Output
56
71
  TXT
57
72
  end
58
73
 
59
- if !base_paths.one?
74
+ if !base_paths.compact_blank.empty? && !base_paths.one?
60
75
  raise InconsistentBasePathError.new <<~TXT
61
76
  There are requests with different base paths in the same documentation,
62
77
  which is not supported by Swagger.
@@ -69,7 +84,7 @@ module Explicit::Documentation::Output
69
84
  TXT
70
85
  end
71
86
 
72
- base_urls.first + base_paths.first
87
+ (base_urls.first || "") + (base_paths.first || "")
73
88
  end
74
89
 
75
90
  def build_tags_from_sections
@@ -86,13 +101,23 @@ module Explicit::Documentation::Output
86
101
  request = page.request
87
102
  route = request.routes.first
88
103
 
104
+ security =
105
+ if request.requires_basic_authorization?
106
+ [ { basicAuth: [] } ]
107
+ elsif request.requires_bearer_authorization?
108
+ [ { bearerAuth: [] } ]
109
+ else
110
+ nil
111
+ end
112
+
89
113
  paths[route.path_with_curly_syntax][route.method.to_s] = {
90
- tags: [section.name],
114
+ tags: [ section.name ],
91
115
  summary: request.get_title,
92
116
  description: request.get_description,
93
117
  parameters: build_parameters(request),
94
118
  requestBody: build_request_body(request),
95
- responses: build_responses(request)
119
+ responses: build_responses(request),
120
+ security:
96
121
  }.compact_blank
97
122
  end
98
123
  end
@@ -102,7 +127,11 @@ module Explicit::Documentation::Output
102
127
 
103
128
  def build_parameters(request)
104
129
  headers =
105
- request.headers_type.attributes.map do |name, type|
130
+ request.headers_type.attributes.filter_map do |name, type|
131
+ # NOTE: skip Authorization header because swagger prefers the `security` directive for basic and bearer
132
+ # authorization schemas. If not basic or bearer, then we add the Authorization header.
133
+ next if name == "Authorization" && !request.custom_authorization_format?
134
+
106
135
  {
107
136
  name: name.to_s,
108
137
  in: "header",
@@ -132,7 +161,7 @@ module Explicit::Documentation::Output
132
161
 
133
162
  return nil if body_params_type.attributes.empty?
134
163
 
135
- examples =
164
+ examples =
136
165
  request.examples
137
166
  .flat_map { |_, examples| examples }
138
167
  .filter_map do |example|
@@ -141,7 +170,7 @@ module Explicit::Documentation::Output
141
170
  in [:error, _] then nil
142
171
  end
143
172
  end
144
- .map.with_index { |example, index| [index, { value: example }] }
173
+ .map.with_index { |example, index| [ index, { value: example } ] }
145
174
  .to_h
146
175
 
147
176
  {
@@ -160,7 +189,7 @@ module Explicit::Documentation::Output
160
189
 
161
190
  request.responses.each do |status, _|
162
191
  examples = request.examples[status].map.with_index do |example, index|
163
- [index.to_s, { value: example.response.data }]
192
+ [ index.to_s, { value: example.response.data } ]
164
193
  end.to_h
165
194
 
166
195
  responses[status] = {
@@ -12,13 +12,15 @@ class Explicit::Request
12
12
 
13
13
  instance_eval(&block)
14
14
 
15
+ define_missing_path_params!
16
+
15
17
  if Explicit.configuration.rescue_from_invalid_params? && @params.any?
16
18
  @responses[422] << {
17
19
  error: "invalid_params",
18
20
  params: [
19
21
  :description,
20
22
  "An object containing error messages for all invalid params",
21
- [:hash, :string, :string]
23
+ [ :hash, :string, :string ]
22
24
  ]
23
25
  }
24
26
  end
@@ -76,19 +78,19 @@ class Explicit::Request
76
78
  raise ArgumentError("duplicated param #{name}") if @params.key?(name)
77
79
 
78
80
  if options[:optional]
79
- type = [:nilable, type]
81
+ type = [ :nilable, type ]
80
82
  end
81
83
 
82
84
  if (defaultval = options[:default])
83
- type = [:default, defaultval, type]
85
+ type = [ :default, defaultval, type ]
84
86
  end
85
87
 
86
88
  if (description = options[:description])
87
- type = [:description, description, type]
89
+ type = [ :description, description, type ]
88
90
  end
89
91
 
90
92
  if @routes.first&.params&.include?(name)
91
- type = [:_param_location, :path, type]
93
+ type = [ :_param_location, :path, type ]
92
94
  end
93
95
 
94
96
  @params[name] = type
@@ -140,6 +142,31 @@ class Explicit::Request
140
142
  end
141
143
 
142
144
  def responses_type(status:)
143
- Explicit::Type.build([:one_of, *@responses[status]])
145
+ Explicit::Type.build([ :one_of, *@responses[status] ])
146
+ end
147
+
148
+ def custom_authorization_format?
149
+ @headers.key?("Authorization") && !requires_basic_authorization? && !requires_bearer_authorization?
150
+ end
151
+
152
+ def requires_basic_authorization?
153
+ authorization = headers_type.attributes["Authorization"]
154
+
155
+ authorization&.format&.to_s&.include?("Basic")
144
156
  end
157
+
158
+ def requires_bearer_authorization?
159
+ authorization = headers_type.attributes["Authorization"]
160
+
161
+ authorization&.format&.to_s&.include?("Bearer")
162
+ end
163
+
164
+ private
165
+ def define_missing_path_params!
166
+ @routes.first&.params&.each do |path_param_name|
167
+ if @params[path_param_name.to_sym].blank?
168
+ param(path_param_name.to_sym, :string)
169
+ end
170
+ end
171
+ end
145
172
  end
@@ -11,7 +11,7 @@ class Explicit::Type::Date < Explicit::Type
11
11
  end
12
12
 
13
13
  def validate(value)
14
- return [:ok, value] if value.is_a?(::Date)
14
+ return [ :ok, value ] if value.is_a?(::Date)
15
15
  return error_i18n("string") if !value.is_a?(::String)
16
16
 
17
17
  date = ::Date.parse(value, false)
@@ -32,7 +32,7 @@ class Explicit::Type::Date < Explicit::Type
32
32
  end
33
33
  end
34
34
 
35
- [:ok, date]
35
+ [ :ok, date ]
36
36
  rescue ::Date::Error
37
37
  error_i18n("date_format")
38
38
  end
@@ -53,14 +53,14 @@ class Explicit::Type::Date < Explicit::Type
53
53
 
54
54
  concerning :Swagger do
55
55
  def swagger_schema
56
- {
56
+ merge_base_swagger_schema({
57
57
  type: "string",
58
58
  pattern: /\d{4}-\d{2}-\d{2}/.inspect[1..-2],
59
59
  format: "date",
60
60
  description_topics: [
61
61
  swagger_i18n("date_format")
62
62
  ]
63
- }
63
+ })
64
64
  end
65
65
  end
66
66
  end
@@ -0,0 +1,87 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Explicit::Type::Float < Explicit::Type
4
+ attr_reader :min, :max, :negative, :positive
5
+
6
+ def initialize(min: nil, max: nil, negative: nil, positive: nil)
7
+ @min = min
8
+ @max = max
9
+ @negative = negative
10
+ @positive = positive
11
+ end
12
+
13
+ ParseFromString = ->(value) do
14
+ Float(value)
15
+ rescue ::ArgumentError
16
+ nil
17
+ end
18
+
19
+ def validate(value)
20
+ value =
21
+ if value.is_a?(::Integer) || value.is_a?(::Float) || value.is_a?(::BigDecimal)
22
+ value
23
+ elsif value.is_a?(::String)
24
+ ParseFromString[value]
25
+ else
26
+ nil
27
+ end
28
+
29
+ return error_i18n("float") if value.nil?
30
+
31
+ if min && value < min
32
+ return error_i18n("min", min:)
33
+ end
34
+
35
+ if max && value > max
36
+ return error_i18n("max", max:)
37
+ end
38
+
39
+ if negative == false && value < 0
40
+ return error_i18n("not_negative")
41
+ end
42
+
43
+ if negative == true && value >= 0
44
+ return error_i18n("only_negative")
45
+ end
46
+
47
+ if positive == false && value > 0
48
+ return error_i18n("not_positive")
49
+ end
50
+
51
+ if positive == true && value <= 0
52
+ return error_i18n("only_positive")
53
+ end
54
+
55
+ [ :ok, value ]
56
+ end
57
+
58
+ concerning :Webpage do
59
+ def summary
60
+ "float"
61
+ end
62
+
63
+ def partial
64
+ "explicit/documentation/type/float"
65
+ end
66
+
67
+ def has_details?
68
+ min.present? || max.present? || !negative.nil? || !positive.nil?
69
+ end
70
+ end
71
+
72
+ concerning :Swagger do
73
+ def swagger_schema
74
+ merge_base_swagger_schema({
75
+ type: "number",
76
+ minimum: min,
77
+ maximum: max,
78
+ description_topics: [
79
+ positive == false ? swagger_i18n("number_not_positive") : nil,
80
+ positive == true ? swagger_i18n("number_only_positive") : nil,
81
+ negative == false ? swagger_i18n("number_not_negative") : nil,
82
+ negative == true ? swagger_i18n("number_only_negative") : nil
83
+ ]
84
+ })
85
+ end
86
+ end
87
+ end
@@ -40,11 +40,19 @@ class Explicit::Type::Integer < Explicit::Type
40
40
  return error_i18n("not_negative")
41
41
  end
42
42
 
43
+ if negative == true && value >= 0
44
+ return error_i18n("only_negative")
45
+ end
46
+
43
47
  if positive == false && value > 0
44
48
  return error_i18n("not_positive")
45
49
  end
46
50
 
47
- [:ok, value]
51
+ if positive == true && value <= 0
52
+ return error_i18n("only_positive")
53
+ end
54
+
55
+ [ :ok, value ]
48
56
  end
49
57
 
50
58
  concerning :Webpage do
@@ -68,10 +76,10 @@ class Explicit::Type::Integer < Explicit::Type
68
76
  minimum: min,
69
77
  maximum: max,
70
78
  description_topics: [
71
- positive == false ? swagger_i18n("integer_not_positive") : nil,
72
- positive == true ? swagger_i18n("integer_only_positive") : nil,
73
- negative == false ? swagger_i18n("integer_not_negative") : nil,
74
- negative == true ? swagger_i18n("integer_only_negative") : nil
79
+ positive == false ? swagger_i18n("number_not_positive") : nil,
80
+ positive == true ? swagger_i18n("number_only_positive") : nil,
81
+ negative == false ? swagger_i18n("number_not_negative") : nil,
82
+ negative == true ? swagger_i18n("number_only_negative") : nil
75
83
  ]
76
84
  })
77
85
  end
@@ -27,28 +27,35 @@ class Explicit::Type::OneOf < Explicit::Type
27
27
  @subtypes.each do |subtype|
28
28
  case subtype.validate(value)
29
29
  in [:ok, validated_value]
30
- return [:ok, validated_value]
30
+ return [ :ok, validated_value ]
31
31
  in [:error, err]
32
32
  errors << err
33
33
  end
34
34
  end
35
35
 
36
36
  if (err = guess_error_for_intended_subtype_via_matching_literal(value:, errors:))
37
- return [:error, err]
37
+ return [ :error, err ]
38
38
  end
39
39
 
40
40
  if (err = guess_error_for_intended_subtype_via_matching_keys(value:, errors:))
41
- return [:error, err]
41
+ return [ :error, err ]
42
42
  end
43
43
 
44
+ separator =
45
+ if ::I18n.exists?("explicit.errors.one_of_separator")
46
+ ::I18n.t("explicit.errors.one_of_separator")
47
+ else
48
+ ::I18n.t("explicit.errors.one_of_separator", locale: :en)
49
+ end
50
+
44
51
  error =
45
52
  if @subtypes_are_records
46
- errors.map { ::JSON.pretty_generate(_1) }.join("\n\n#{ ::I18n.t('explicit.errors.one_of_separator')}\n\n")
53
+ errors.map { ::JSON.pretty_generate(_1) }.join("\n\n#{separator}\n\n")
47
54
  else
48
- errors.join(" #{I18n.t('explicit.errors.one_of_separator')} ")
55
+ errors.join(" #{separator} ")
49
56
  end
50
57
 
51
- [:error, error]
58
+ [ :error, error ]
52
59
  end
53
60
 
54
61
  def guess_error_for_intended_subtype_via_matching_literal(value:, errors:)
@@ -101,4 +108,4 @@ class Explicit::Type::OneOf < Explicit::Type
101
108
  { oneOf: subtypes.map(&:swagger_schema) }
102
109
  end
103
110
  end
104
- end
111
+ end
data/lib/explicit/type.rb CHANGED
@@ -59,6 +59,11 @@ class Explicit::Type
59
59
  in [:file, options]
60
60
  Explicit::Type::File.new(**options)
61
61
 
62
+ in :float
63
+ Explicit::Type::Float.new
64
+ in [:float, options]
65
+ Explicit::Type::Float.new(**options)
66
+
62
67
  in :integer
63
68
  Explicit::Type::Integer.new
64
69
  in [:integer, options]
@@ -109,13 +114,24 @@ class Explicit::Type
109
114
  def error_i18n(name, context = {})
110
115
  key = "explicit.errors.#{name}"
111
116
 
112
- [:error, ::I18n.t(key, **context)]
117
+ translation =
118
+ if ::I18n.exists?(key)
119
+ ::I18n.t(key, **context)
120
+ else
121
+ ::I18n.t(key, **context.merge(locale: :en))
122
+ end
123
+
124
+ [ :error, translation ]
113
125
  end
114
126
 
115
127
  def swagger_i18n(name, context = {})
116
128
  key = "explicit.swagger.#{name}"
117
129
 
118
- ::I18n.t(key, **context)
130
+ if ::I18n.exists?(key)
131
+ ::I18n.t(key, **context)
132
+ else
133
+ ::I18n.t(key, **context.merge(locale: :en))
134
+ end
119
135
  end
120
136
 
121
137
  def merge_base_swagger_schema(attributes)
@@ -144,4 +160,4 @@ class Explicit::Type
144
160
 
145
161
  base_attributes.merge(attributes).compact_blank
146
162
  end
147
- end
163
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Explicit
4
- VERSION = "0.2.7"
4
+ VERSION = "0.2.9"
5
5
  end
data/lib/explicit.rb CHANGED
@@ -35,6 +35,7 @@ require "explicit/type/date_time_unix_epoch"
35
35
  require "explicit/type/date"
36
36
  require "explicit/type/enum"
37
37
  require "explicit/type/file"
38
+ require "explicit/type/float"
38
39
  require "explicit/type/hash"
39
40
  require "explicit/type/integer"
40
41
  require "explicit/type/literal"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: explicit
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.7
4
+ version: 0.2.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Luiz Vasconcellos
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-01-31 00:00:00.000000000 Z
11
+ date: 2025-02-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -66,6 +66,7 @@ files:
66
66
  - app/views/explicit/documentation/type/_date_time_unix_epoch.html.erb
67
67
  - app/views/explicit/documentation/type/_enum.html.erb
68
68
  - app/views/explicit/documentation/type/_file.html.erb
69
+ - app/views/explicit/documentation/type/_float.html.erb
69
70
  - app/views/explicit/documentation/type/_hash.html.erb
70
71
  - app/views/explicit/documentation/type/_integer.html.erb
71
72
  - app/views/explicit/documentation/type/_one_of.html.erb
@@ -104,6 +105,7 @@ files:
104
105
  - lib/explicit/type/date_time_unix_epoch.rb
105
106
  - lib/explicit/type/enum.rb
106
107
  - lib/explicit/type/file.rb
108
+ - lib/explicit/type/float.rb
107
109
  - lib/explicit/type/hash.rb
108
110
  - lib/explicit/type/integer.rb
109
111
  - lib/explicit/type/literal.rb