dry-types-json-schema 0.0.2 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d53a441b9ed9f57e185e971538b1a3b3f81038527e9f071c7af8fbfb8cd10a3c
4
- data.tar.gz: d6693481b3aaa1d6b5b81b34ae91c90eea58758f094681b68ea11f9fca5ea34c
3
+ metadata.gz: 67e63d34a8b81578fef86941bd3f448062ddf6357f5ea66751882f424a52bd28
4
+ data.tar.gz: 732938510bbdfa5490421cebfff6de06b57108819bdc0f7f7806f03ad4c8131b
5
5
  SHA512:
6
- metadata.gz: 939497ac477bdc404b3ab166f3af9d2f42260617f96f145e73921d0dc721a57cea618d48b4738958b322be5c549268829fda68bd7309487db1e1695f47da3b16
7
- data.tar.gz: 4e86da1db6970398e73fb22ee6d7dd3e1505198705bdcc0cddf28d7df849afcd521703043e6a550e42ee75bd526d30ecf5077d81b048498f914251554095ff26
6
+ metadata.gz: a0133a959fe532c4f5c75a5084c674a2e83553af6e6abb6580a1809fba8f5dd15c748640c786f4d22cd04a00303582ddc3ef957b707ec00d17281621bf4e6ad7
7
+ data.tar.gz: 05b90642aa10bce11add57b7591fa466a0102f9c5d62e4fa29b8a2f0a1318908d0a10baf9c36531fadf5584764d740b0beb3a7e21b540be63eb03a4b23f03ba0
@@ -0,0 +1,12 @@
1
+ name: Test
2
+ on: [push, pull_request]
3
+ jobs:
4
+ test:
5
+ runs-on: ubuntu-latest
6
+ steps:
7
+ - uses: actions/checkout@v4
8
+ - uses: ruby/setup-ruby@v1
9
+ with:
10
+ ruby-version: '3.3'
11
+ bundler-cache: true
12
+ - run: bundle exec make test
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- dry-types-json-schema (0.0.2)
4
+ dry-types-json-schema (0.0.4)
5
5
  dry-types (~> 1.7.2)
6
6
 
7
7
  GEM
@@ -2,7 +2,7 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = "dry-types-json-schema"
5
- s.version = "0.0.2"
5
+ s.version = "0.0.4"
6
6
  s.summary = "Generate JSON Schema from dry-types"
7
7
  s.authors = ["elcuervo"]
8
8
  s.licenses = %w[MIT]
@@ -17,7 +17,7 @@ module Dry
17
17
  IDENTITY = ->(v, _) { v }.freeze
18
18
  INSPECT = ->(v, _) { v.inspect }.freeze
19
19
  TO_INTEGER = ->(v, _) { v.to_i }.freeze
20
- TO_ARRAY = ->(v, _) { v.to_a }.freeze
20
+ TO_ARRAY = ->(v, _) { Array(v) }.freeze
21
21
  TO_TYPE = ->(v, _) { CLASS_TO_TYPE.fetch(v.to_s.to_sym) }.freeze
22
22
 
23
23
  # Metadata annotations and allowed types overrides for schema generation.
@@ -161,21 +161,33 @@ module Dry
161
161
 
162
162
  definition.transform_values! { |v| v.call(type, ctx) }
163
163
 
164
- return unless definition.any? && ctx
164
+ return unless definition.any?
165
165
 
166
166
  if (extra = EXTRA_PROPS_FOR_TYPE[type.to_s.to_sym])
167
167
  definition = definition.merge(extra)
168
168
  end
169
169
 
170
- @keys[ctx] ||= {}
171
- @keys[ctx].merge!(definition)
170
+ if ctx.nil?
171
+ @keys.merge!(definition)
172
+ else
173
+ @keys[ctx] ||= {}
174
+ @keys[ctx].merge!(definition)
175
+ end
176
+ end
177
+
178
+ def visit_intersection(node, opts = EMPTY_HASH)
179
+ *types, _ = node
180
+
181
+ result = types.map { |type| compile_type(type) }
182
+
183
+ @keys[opts[:key]] = deep_merge_items(result)
172
184
  end
173
185
 
174
186
  def visit_sum(node, opts = EMPTY_HASH)
175
187
  *types, _ = node
176
188
 
177
189
  result = types
178
- .map { |type| single_type(type, opts.merge(sum: true)) }
190
+ .map { |type| compile_value(type, opts.merge(sum: true)) }
179
191
  .uniq
180
192
 
181
193
  return @keys[opts[:key]] = result.first if result.count == 1
@@ -205,14 +217,9 @@ module Dry
205
217
  def visit_struct(node, opts = EMPTY_HASH)
206
218
  _, schema = node
207
219
 
208
- if opts[:key]
209
- target = self.class.new
210
- target.visit(schema)
220
+ return visit(schema, opts) unless opts[:key]
211
221
 
212
- @keys[opts[:key]] = target.to_hash
213
- else
214
- visit(schema, opts)
215
- end
222
+ @keys[opts[:key]] = compile_type(schema)
216
223
  end
217
224
 
218
225
  def visit_array(node, opts = EMPTY_HASH)
@@ -253,12 +260,29 @@ module Dry
253
260
 
254
261
  private
255
262
 
256
- # FIXME: cleaner way to generate individual types
257
- #
258
- def single_type(type, opts)
263
+ def deep_merge_items(items)
264
+ items.reduce({}) do |current, target|
265
+ current.merge(target) do |_, from, to|
266
+ case [from.class, to.class]
267
+ when [::Hash, ::Hash]
268
+ deep_merge_items([from, to])
269
+ when [::Array, ::Array]
270
+ from | to
271
+ else
272
+ to
273
+ end
274
+ end
275
+ end
276
+ end
277
+
278
+ def compile_type(type, opts = EMPTY_HASH)
259
279
  self.class.new
260
280
  .tap { |target| target.visit(type, opts) }
261
281
  .to_hash
282
+ end
283
+
284
+ def compile_value(type, opts = EMPTY_HASH)
285
+ compile_type(type, opts)
262
286
  .values
263
287
  .first
264
288
  end
@@ -16,6 +16,14 @@ describe Dry::Types::JSONSchema do
16
16
  { type: :string, format: :email, title: title }
17
17
  end
18
18
  end
19
+
20
+ it_conforms_definition do
21
+ let(:type) { Dry::Types["string"].enum(*%w[a b]) }
22
+
23
+ let(:definition) do
24
+ { type: :string, enum: %w[a b] }
25
+ end
26
+ end
19
27
  end
20
28
 
21
29
  describe "hash" do
@@ -70,6 +78,9 @@ describe Dry::Types::JSONSchema do
70
78
  .of(Types::String)
71
79
  .constrained(min_size: 1)
72
80
 
81
+ BasicHash = Types::Hash.schema(name: Types::String)
82
+ ExtendedHash = Types::Hash.schema(age: Types::Integer) & BasicHash
83
+
73
84
  attribute :data, Types::String | Types::Hash
74
85
  attribute :string, Types::String.constrained(min_size: 1, max_size: 255)
75
86
  attribute :list, VariableList
@@ -81,6 +92,8 @@ describe Dry::Types::JSONSchema do
81
92
  attribute? :meta, Types::String.meta(format: :email)
82
93
  attribute? :enum, Types::String.enum(*%w[draft published archived])
83
94
  attribute? :array, ArrayOfStrings
95
+ attribute? :inter, ExtendedHash
96
+
84
97
  attribute? :nested do
85
98
  attribute :deep, Types::Integer
86
99
  end
@@ -162,6 +175,15 @@ describe Dry::Types::JSONSchema do
162
175
  items: { type: :string }
163
176
  },
164
177
 
178
+ inter: {
179
+ type: :object,
180
+ properties: {
181
+ age: { type: :integer },
182
+ name: { type: :string }
183
+ },
184
+ required: %i[age name]
185
+ },
186
+
165
187
  nested: {
166
188
  type: :object,
167
189
  properties: {
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dry-types-json-schema
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - elcuervo
@@ -143,6 +143,7 @@ executables: []
143
143
  extensions: []
144
144
  extra_rdoc_files: []
145
145
  files:
146
+ - ".github/workflows/test.yml"
146
147
  - ".gitignore"
147
148
  - ".rubocop.yml"
148
149
  - Gemfile