verse-schema 1.1.0 → 1.2.0

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: 63618ff4cf11b43ec35e8bb88adaffdf8d15ac3a49a461427fbdc3cd8908299a
4
- data.tar.gz: 2ab22e1cd477e2b4f0e4cd070f50e2fd56e89b1c323795f4ca3cbfa1944e271d
3
+ metadata.gz: ac21990f8abf487af0be8d14959c40595c2327cdbbda87a4bc15d53cfcf87a36
4
+ data.tar.gz: 102efefd85e3181bda88e337672a810c54bfafe4c623ae825972b7e82e6bc689
5
5
  SHA512:
6
- metadata.gz: d7c5cb3e34919f47de38726ea146aa1d3d3ffe77b26d999c18da1d5e441ca06fcba4d8827c42d3b515ea7c7abd73177e7627352e1c2714ef82c0e2e196b9d01a
7
- data.tar.gz: 4b60874afb6bcf4b7721396b9fe799b38b1b21fe4fb31c9b8fd467b835ded25ff72f8df8a2ff7bb4cddd1dca322937aa8ad1f879bcc13e7d9e012cf027cc4f63
6
+ metadata.gz: 1e464f3fcbaa0d77b69d81f7001c80ecb7efba9298476aab84f16390bbda8481c1f37c3c7a5d80e11d9de31f7064c67e9db1448b545d4b927079d331ea939b3d
7
+ data.tar.gz: 89cfcaa93e6813a5ffab8834e49002ebf3791a42a64a5457444a0fa4ba941412583ea1925e5ba7c607e7bfcd3bd16628437f9c954b6710f6296f400b9b0d3be7
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ ruby-3.4.3
data/CHANGELOG.md CHANGED
@@ -1,3 +1,8 @@
1
+ ## 1.2
2
+
3
+ - Add `Verse::Schema::Json.from` method to convert a Verse schema
4
+ to JSON Schema format (note: doesn't work the other way around yet)
5
+
1
6
  ## 1.1
2
7
 
3
8
  - Add `strict` mode to `validate` which will raise an error if the input has
data/Gemfile CHANGED
@@ -7,7 +7,7 @@ gemspec
7
7
 
8
8
  # Development dependencies
9
9
  group :development do
10
- gem "prism", "~> 0.19.0", require: false
10
+ gem "prism", "~> 1.5.2", require: false
11
11
  end
12
12
 
13
13
  gem "rake", "~> 13.0"
@@ -18,6 +18,6 @@ gem "relaxed-rubocop"
18
18
  gem "rubocop", "~> 1.21"
19
19
  gem "simplecov"
20
20
 
21
- gem "ruby-prof"
21
+ gem "ruby-prof", "~> 1.7.2"
22
22
 
23
23
  gem "rspec", "~> 3.0"
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- verse-schema (1.1.0)
4
+ verse-schema (1.2.0)
5
5
  attr_chainable (~> 1.0)
6
6
 
7
7
  GEM
@@ -9,6 +9,7 @@ GEM
9
9
  specs:
10
10
  ast (2.4.2)
11
11
  attr_chainable (1.0.0)
12
+ base64 (0.3.0)
12
13
  bootsnap (1.18.3)
13
14
  msgpack (~> 1.2)
14
15
  coderay (1.1.3)
@@ -22,7 +23,7 @@ GEM
22
23
  parser (3.3.0.5)
23
24
  ast (~> 2.4.1)
24
25
  racc
25
- prism (0.19.0)
26
+ prism (1.5.2)
26
27
  pry (0.14.2)
27
28
  coderay (~> 1.1)
28
29
  method_source (~> 1.0)
@@ -58,7 +59,8 @@ GEM
58
59
  unicode-display_width (>= 2.4.0, < 3.0)
59
60
  rubocop-ast (1.31.2)
60
61
  parser (>= 3.3.0.4)
61
- ruby-prof (1.7.1)
62
+ ruby-prof (1.7.2)
63
+ base64
62
64
  ruby-progressbar (1.13.0)
63
65
  simplecov (0.22.0)
64
66
  docile (~> 1.1)
@@ -73,13 +75,13 @@ PLATFORMS
73
75
 
74
76
  DEPENDENCIES
75
77
  bootsnap (~> 1.16)
76
- prism (~> 0.19.0)
78
+ prism (~> 1.5.2)
77
79
  pry
78
80
  rake (~> 13.0)
79
81
  relaxed-rubocop
80
82
  rspec (~> 3.0)
81
83
  rubocop (~> 1.21)
82
- ruby-prof
84
+ ruby-prof (~> 1.7.2)
83
85
  simplecov
84
86
  verse-schema!
85
87
 
data/README.md CHANGED
@@ -123,6 +123,11 @@ These examples are extracted directly from the gem's specs, ensuring they are ac
123
123
  - [Polymorphic Schema](#polymorphic-schema)
124
124
 
125
125
 
126
+ - [JSON Schema Generation](#json-schema-generation)
127
+
128
+ - [Generating JSON Schema](#generating-json-schema)
129
+
130
+
126
131
 
127
132
 
128
133
  ## 1. Basic Usage
@@ -952,7 +957,7 @@ it "demonstrates reusable rules defined with Verse::Schema.rule" do
952
957
  is_positive = Verse::Schema.rule("must be positive") { |value| value > 0 }
953
958
 
954
959
  # Define another reusable rule
955
- is_even = Verse::Schema.rule("must be even") { |value| value.even? }
960
+ is_even = Verse::Schema.rule("must be even", &:even?)
956
961
 
957
962
  # Create a schema that uses the reusable rules
958
963
  schema = Verse::Schema.define do
@@ -1666,7 +1671,6 @@ it "demonstrates a polymorphic schema" do
1666
1671
  # 3. Define a builder schema. The best way to do this is to use the
1667
1672
  # scalar type:
1668
1673
  builder_schema = Verse::Schema.scalar(Hash).transform do |input, error_builder|
1669
-
1670
1674
  type = input[:type]
1671
1675
 
1672
1676
  if type.respond_to?(:to_sym)
@@ -1677,14 +1681,14 @@ it "demonstrates a polymorphic schema" do
1677
1681
  end
1678
1682
 
1679
1683
  schema = case type
1680
- when :facebook
1681
- facebook_schema
1682
- when :google
1683
- google_schema
1684
- else
1685
- error_builder.add(:type, "invalid type")
1686
- stop
1687
- end
1684
+ when :facebook
1685
+ facebook_schema
1686
+ when :google
1687
+ google_schema
1688
+ else
1689
+ error_builder.add(:type, "invalid type")
1690
+ stop
1691
+ end
1688
1692
 
1689
1693
  # Validate the input against the selected schema
1690
1694
  result = schema.validate(input, error_builder:)
@@ -1753,9 +1757,9 @@ it "demonstrates a polymorphic schema" do
1753
1757
  expect(invalid_result.success?).to be false
1754
1758
  # The errors are collected
1755
1759
  expect(invalid_result.errors).to eq({
1756
- :"events.0.url" => ["is required"],
1757
- :"events.1.location" => ["is required"],
1758
- :"events.2.type" => ["invalid type"]
1760
+ "events.0.url": ["is required"],
1761
+ "events.1.location": ["is required"],
1762
+ "events.2.type": ["invalid type"]
1759
1763
  })
1760
1764
  end
1761
1765
 
@@ -1763,6 +1767,47 @@ end
1763
1767
 
1764
1768
 
1765
1769
 
1770
+ ## JSON Schema Generation
1771
+
1772
+
1773
+ ### Generating JSON Schema
1774
+
1775
+
1776
+ ```ruby
1777
+ it "converts a simple schema to a valid JSON schema" do
1778
+ schema = Verse::Schema.define do
1779
+ field(:name, String).meta(description: "The name of the user")
1780
+ field(:age, Integer)
1781
+ end
1782
+
1783
+ json_schema = Verse::Schema::Json.from(schema)
1784
+ puts JSON.pretty_generate(json_schema)
1785
+
1786
+ # The output of the `to_json` method will be a valid JSON schema hash:
1787
+ #
1788
+ # {
1789
+ # "type": "object",
1790
+ # "properties": {
1791
+ # "name": {
1792
+ # "type": "string",
1793
+ # "description": "The name of the user"
1794
+ # },
1795
+ # "age": {
1796
+ # "type": "integer"
1797
+ # }
1798
+ # },
1799
+ # "required": [
1800
+ # "name",
1801
+ # "age"
1802
+ # ],
1803
+ # "additionalProperties": false
1804
+ # }
1805
+ end
1806
+
1807
+ ```
1808
+
1809
+
1810
+
1766
1811
 
1767
1812
  ## License
1768
1813
 
@@ -109,7 +109,7 @@ class ReadmeDocExtractor
109
109
  end
110
110
  end
111
111
 
112
- # Extract code from an example
112
+ # Extract code from an example
113
113
  def extract_code_from_example(example)
114
114
  # Get the example block directly using instance_variable_get
115
115
  example_block = example.instance_variable_get(:@example_block)
@@ -14,7 +14,7 @@ module Verse
14
14
 
15
15
  # Initialize a new schema.
16
16
  def initialize(post_processors: nil)
17
- @post_processors = post_processors
17
+ @post_processors = post_processors
18
18
  end
19
19
 
20
20
  def rule(fields = nil, message = "rule failed", &block)
@@ -10,7 +10,7 @@ module Verse
10
10
  DEFAULT_MAPPER = lambda do |type|
11
11
  if type.is_a?(Base)
12
12
  proc do |value, _opts, locals:, strict:|
13
- type.validate(value, locals:, strict:)
13
+ type.validate(value, locals:, strict:)
14
14
  end
15
15
  elsif type.is_a?(Class)
16
16
  proc do |value|
@@ -57,10 +57,28 @@ module Verse
57
57
  @values.all? do |child_type|
58
58
  # ...is a subtype (`<=`) of *at least one* type allowed by the parent collection.
59
59
  parent_schema.values.any? do |parent_type|
60
- # Use the existing `<=` operator defined on schema types (Scalar, Struct, etc.)
61
- # This assumes the `<=` operator correctly handles class inheritance (e.g., Integer <= Object)
62
- # and schema type compatibility.
63
- child_type <= parent_type
60
+ # Special handling for when child_type is a primitive class (like Integer)
61
+ # and parent_type is a Scalar
62
+ if !child_type.is_a?(Base) && parent_type.is_a?(Scalar)
63
+ # Check if the primitive class is compatible with any of the Scalar's values
64
+ parent_type.values.any? do |scalar_value|
65
+ # Use standard Ruby `<=` for comparison
66
+ child_type <= scalar_value
67
+ rescue TypeError
68
+ # Handle cases where <= is not defined between types
69
+ false
70
+ end
71
+ else
72
+ # Use the existing `<=` operator defined on schema types (Scalar, Struct, etc.)
73
+ # This assumes the `<=` operator correctly handles class inheritance (e.g., Integer <= Object)
74
+ # and schema type compatibility.
75
+ begin
76
+ child_type <= parent_type
77
+ rescue TypeError
78
+ # Handle cases where <= is not defined between types
79
+ false
80
+ end
81
+ end
64
82
  end
65
83
  end
66
84
  end
@@ -170,7 +188,6 @@ module Verse
170
188
 
171
189
  Result.new(output, error_builder.errors)
172
190
  end
173
-
174
191
  end
175
192
  end
176
193
  end
@@ -14,7 +14,7 @@ module Verse
14
14
  def initialize(values:, post_processors: nil)
15
15
  super(post_processors:)
16
16
 
17
- @values = values
17
+ @values = values
18
18
  end
19
19
 
20
20
  def validate(input, error_builder: nil, locals: {}, strict: false)
@@ -155,7 +155,6 @@ module Verse
155
155
 
156
156
  Result.new(output, error_builder.errors)
157
157
  end
158
-
159
158
  end
160
159
  end
161
160
  end
@@ -8,7 +8,7 @@ module Verse
8
8
  module Schema
9
9
  # A field in a schema
10
10
  class Field
11
- attr_reader :opts, :post_processors, :name, :type
11
+ attr_reader :opts, :post_processors, :name
12
12
 
13
13
  def initialize(name, type, opts, post_processors: nil, &block)
14
14
  @name = name
@@ -53,7 +53,7 @@ module Verse
53
53
  of_arg = @opts[:of] # For array and dictionary
54
54
  of_arg = [of_arg] unless of_arg.nil? || of_arg.is_a?(Array)
55
55
 
56
- if type == Hash || type == Object
56
+ if [Hash, Object].include?(type)
57
57
  type = Schema.dictionary(*of_arg) if of_arg # dictionary
58
58
  elsif type == Array
59
59
  type = Schema.array(*of_arg) if of_arg
@@ -269,7 +269,7 @@ module Verse
269
269
  elsif c.is_a?(Class) && p.is_a?(Verse::Schema::Scalar)
270
270
  p.values.any? { |p_val| c <= p_val }
271
271
  elsif c.is_a?(Verse::Schema::Base) && p.is_a?(Verse::Schema::Base)
272
- c <= p
272
+ c <= p
273
273
  elsif c.is_a?(Class) && p.is_a?(Class)
274
274
  c <= p
275
275
  else
@@ -0,0 +1,160 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Verse
4
+ module Schema
5
+ module Json
6
+ # rubocop:disable Lint/HashCompareByIdentity
7
+ # @param schema [Verse::Schema::Base] The schema to convert to JSON schema
8
+ # @return [Hash] The JSON schema
9
+ def self.from(schema)
10
+ definitions = {}
11
+ # directly build the root schema, don't use a ref.
12
+ output = _build_schema(schema, registry: {}, definitions: definitions)
13
+
14
+ if definitions.any?
15
+ output[:"$defs"] = definitions
16
+ end
17
+
18
+ output
19
+ end
20
+
21
+ def self._from_schema(schema, registry:, definitions:)
22
+ return { "$ref": registry[schema.object_id] } if registry.key?(schema.object_id)
23
+
24
+ if schema.is_a?(Verse::Schema::Struct)
25
+ # Register the schema to handle recursion
26
+ # and give it a name.
27
+ # The name is based on the class name, or the object_id if the class is anonymous.
28
+ name = :"Schema#{schema.object_id}"
29
+ ref = "#/$defs/#{name}"
30
+
31
+ registry[schema.object_id] = ref
32
+
33
+ # if it's the root schema, don't create a definition, just build it.
34
+ built_schema = _build_schema(schema, registry:, definitions:)
35
+
36
+ definitions[name] = built_schema
37
+
38
+ return { "$ref": ref }
39
+ end
40
+
41
+ _build_schema(schema, registry:, definitions:)
42
+ end
43
+
44
+ def self._build_schema(schema, registry:, definitions:)
45
+ case schema
46
+ when Verse::Schema::Struct
47
+ properties = schema.fields.each_with_object({}) do |field_obj, obj|
48
+ next if field_obj.type.is_a?(Verse::Schema::Selector)
49
+
50
+ obj[field_obj.name] = begin
51
+ output = _from_schema(field_obj.type, registry:, definitions:)
52
+ desc = field_obj.opts.dig(:meta, :description)
53
+
54
+ output[:description] = desc if desc
55
+
56
+ default = field_obj.opts[:default]
57
+
58
+ if default && !default.is_a?(Proc)
59
+ output[:default] = default
60
+ end
61
+
62
+ output
63
+ end
64
+ end
65
+
66
+ required_fields = schema.fields.select(&:required?).map(&:name)
67
+
68
+ json = {
69
+ type: "object",
70
+ properties: properties
71
+ }
72
+ json[:required] = required_fields if required_fields.any?
73
+ json[:additionalProperties] = schema.extra_fields?
74
+
75
+ # Handle selectors
76
+ schema.fields.each do |field_obj|
77
+ next unless field_obj.type.is_a?(Verse::Schema::Selector)
78
+
79
+ discriminator = field_obj.opts[:over]
80
+ json[:properties][field_obj.name] = { type: "object" }
81
+
82
+ selector_keys = field_obj.type.values.keys
83
+ if !selector_keys.include?(:__else__)
84
+ json[:properties][discriminator][:enum] = selector_keys.map(&:to_s)
85
+ end
86
+
87
+ json[:allOf] = field_obj.type.values.map do |key, sub_schema|
88
+ next if key == :__else__
89
+
90
+ {
91
+ if: {
92
+ properties: { discriminator.to_sym => { const: key.to_s } }
93
+ },
94
+ then: {
95
+ properties: {
96
+ field_obj.name => _from_schema(sub_schema, registry:, definitions:)
97
+ }
98
+ }
99
+ }
100
+ end.compact
101
+ end
102
+
103
+ json
104
+ when Verse::Schema::Collection
105
+ items = if schema.values.length > 1
106
+ { anyOf: schema.values.map { |v| _from_schema(v, registry:, definitions:) } }
107
+ else
108
+ _from_schema(schema.values.first, registry:, definitions:)
109
+ end
110
+
111
+ {
112
+ type: "array",
113
+ items: items
114
+ }
115
+ when Verse::Schema::Dictionary
116
+ additional_properties = if schema.values.length > 1
117
+ { anyOf: schema.values.map { |v| _from_schema(v, registry:, definitions:) } }
118
+ else
119
+ _from_schema(schema.values.first, registry:, definitions:)
120
+ end
121
+ {
122
+ type: "object",
123
+ additionalProperties: additional_properties
124
+ }
125
+ when Verse::Schema::Scalar
126
+ {
127
+ anyOf: schema.values.map { |v| _from_schema(v, registry:, definitions:) }
128
+ }
129
+ when Verse::Schema::Selector
130
+ # This should not be reached directly for a valid schema with `over`
131
+ raise "Selector schema must be used within a Struct with `over` option."
132
+ when String.singleton_class, Symbol.singleton_class
133
+ { type: "string" }
134
+ when Integer.singleton_class
135
+ { type: "integer" }
136
+ when Float.singleton_class, Numeric.singleton_class
137
+ { type: "number" }
138
+ when TrueClass.singleton_class, FalseClass.singleton_class
139
+ { type: "boolean" }
140
+ when Time.singleton_class
141
+ { type: "string", format: "date-time" }
142
+ when NilClass.singleton_class, nil
143
+ { type: "null" }
144
+ when Array
145
+ case schema.length
146
+ when 0
147
+ { type: "null" }
148
+ when 1
149
+ _from_schema(schema.first, registry:, definitions:)
150
+ else
151
+ { anyOf: schema.map { |v| _from_schema(v, registry:, definitions:) } }
152
+ end
153
+ else
154
+ raise "Unknown type #{schema.inspect}"
155
+ end
156
+ end
157
+ # rubocop:enable Metrics/MethodLength, Metrics/CyclomaticComplexity, Lint/HashCompareByIdentity
158
+ end
159
+ end
160
+ end
@@ -65,16 +65,40 @@ module Verse
65
65
  end
66
66
 
67
67
  def <=(other)
68
- other == self || inherit?(other)
68
+ # 1. Identical check: Is it the exact same object?
69
+ return true if other == self
70
+
71
+ # 2. Check if inheriting from another Scalar:
72
+ # Use the existing inherit? method which correctly handles Scalar-to-Scalar inheritance.
73
+ # (inherit? implicitly checks `other.is_a?(Scalar)`)
74
+ return true if inherit?(other)
75
+
76
+ # 3. NEW: Check compatibility with non-Scalar types:
77
+ # If 'other' is not a Scalar, check if any type *wrapped* by this Scalar
78
+ # is a subtype of 'other'. This handles `Scalar<Integer> <= Integer`.
79
+ # We rely on the `<=` operator of the wrapped types themselves.
80
+ @values.any? do |wrapped_type|
81
+ # Use standard Ruby `<=` for comparison.
82
+ # This works for Class <= Class (e.g., Integer <= Integer, Integer <= Numeric)
83
+ # and potentially for SchemaType <= SchemaType if defined.
84
+ wrapped_type <= other
85
+ rescue TypeError
86
+ # Handle cases where <= is not defined between wrapped_type and other
87
+ false
88
+ end
69
89
  end
70
90
 
71
91
  def <(other)
72
- other != self && inherit?(other)
92
+ other != self && self <= other
73
93
  end
74
94
 
75
95
  # rubocop:disable Style/InverseMethods
76
96
  def >(other)
77
- !self.<=(other)
97
+ !(self <= other)
98
+ end
99
+
100
+ def >=(other)
101
+ other <= self
78
102
  end
79
103
  # rubocop:enable Style/InverseMethods
80
104
 
@@ -149,7 +173,6 @@ module Verse
149
173
 
150
174
  Result.new(coalesced_value, error_builder.errors)
151
175
  end
152
-
153
176
  end
154
177
  end
155
178
  end
@@ -221,49 +221,49 @@ module Verse
221
221
  fields << :extra_fields if extra_fields?
222
222
 
223
223
  # Special case for empty schema (yeah, I know, it happens in my production code...)
224
- if fields.empty?
225
- @dataclass = Class.new do
226
- def self.from_raw(*)=new
227
- def self.schema = dataclass_schema
228
-
229
- class_eval(&block) if block
230
- end
231
- else
232
- @dataclass = ::Struct.new(*fields, keyword_init: true) do
233
- # Redefine new method
234
- define_singleton_method(:from_raw, &method(:new))
235
-
236
- define_singleton_method(:new) do |*args, **kwargs|
237
- # Use the schema to generate the hash for our record
238
- if args.size > 1
239
- raise ArgumentError, "You cannot pass more than one argument"
240
- end
241
-
242
- if args.size == 1
243
- if kwargs.any?
244
- raise ArgumentError, "You cannot pass both a hash and keyword arguments"
245
- end
246
-
247
- kwargs = args.first
248
- end
249
-
250
- dataclass_schema.new(kwargs)
251
- end
252
-
253
- define_singleton_method(:schema){ dataclass_schema }
254
-
255
- class_eval(&block) if block
256
- end
257
- end
224
+ @dataclass = if fields.empty?
225
+ Class.new do
226
+ def self.from_raw(*)=new
227
+ def self.schema = dataclass_schema
228
+
229
+ class_eval(&block) if block
230
+ end
231
+ else
232
+ ::Struct.new(*fields, keyword_init: true) do
233
+ # Redefine new method
234
+ define_singleton_method(:from_raw, &method(:new))
235
+
236
+ define_singleton_method(:new) do |*args, **kwargs|
237
+ # Use the schema to generate the hash for our record
238
+ if args.size > 1
239
+ raise ArgumentError, "You cannot pass more than one argument"
240
+ end
241
+
242
+ if args.size == 1
243
+ if kwargs.any?
244
+ raise ArgumentError, "You cannot pass both a hash and keyword arguments"
245
+ end
246
+
247
+ kwargs = args.first
248
+ end
249
+
250
+ dataclass_schema.new(kwargs)
251
+ end
252
+
253
+ define_singleton_method(:schema){ dataclass_schema }
254
+
255
+ class_eval(&block) if block
256
+ end
257
+ end
258
258
  end
259
259
 
260
260
  def inspect
261
261
  fields_string = @fields.map do |field|
262
- if field.type.is_a?(Array)
263
- type_str = field.type.map(&:inspect).join("|")
264
- else
265
- type_str = field.type.inspect
266
- end
262
+ type_str = if field.type.is_a?(Array)
263
+ field.type.map(&:inspect).join("|")
264
+ else
265
+ field.type.inspect
266
+ end
267
267
 
268
268
  optional_marker = field.optional? ? "?" : ""
269
269
  "#{field.name}#{optional_marker}: #{type_str}"
@@ -320,7 +320,6 @@ module Verse
320
320
 
321
321
  Result.new(output, error_builder.errors)
322
322
  end
323
-
324
323
  end
325
324
  end
326
325
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Verse
4
4
  module Schema
5
- VERSION = "1.1.0"
5
+ VERSION = "1.2.0"
6
6
  end
7
7
  end
data/lib/verse/schema.rb CHANGED
@@ -9,6 +9,7 @@ module Verse
9
9
  require_relative "schema/base"
10
10
  require_relative "schema/coalescer"
11
11
  require_relative "schema/post_processor"
12
+ require_relative "schema/json"
12
13
 
13
14
  def define(from = nil, &block)
14
15
  if from
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: verse-schema
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yacine Petitprez
8
8
  bindir: exe
9
9
  cert_chain: []
10
- date: 2025-04-23 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: attr_chainable
@@ -33,6 +33,7 @@ files:
33
33
  - ".rspec"
34
34
  - ".rubocop-https---relaxed-ruby-style-rubocop-yml"
35
35
  - ".rubocop.yml"
36
+ - ".ruby-version"
36
37
  - CHANGELOG.md
37
38
  - Gemfile
38
39
  - Gemfile.lock
@@ -51,6 +52,7 @@ files:
51
52
  - lib/verse/schema/field.rb
52
53
  - lib/verse/schema/field/ext.rb
53
54
  - lib/verse/schema/invalid_schema_error.rb
55
+ - lib/verse/schema/json.rb
54
56
  - lib/verse/schema/optionable.rb
55
57
  - lib/verse/schema/post_processor.rb
56
58
  - lib/verse/schema/result.rb
@@ -78,7 +80,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
78
80
  - !ruby/object:Gem::Version
79
81
  version: '0'
80
82
  requirements: []
81
- rubygems_version: 3.6.3
83
+ rubygems_version: 3.6.7
82
84
  specification_version: 4
83
85
  summary: Consume input schema and output coalesced version of them
84
86
  test_files: []