sober_swag 0.21.0 → 0.24.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (88) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +1 -0
  3. data/CHANGELOG.md +5 -0
  4. data/bin/console +30 -10
  5. data/docs/reporting.md +190 -0
  6. data/example/Gemfile +2 -2
  7. data/example/Gemfile.lock +104 -113
  8. data/example/app/controllers/application_controller.rb +4 -0
  9. data/example/app/controllers/people_controller.rb +44 -28
  10. data/example/app/output_objects/identified_output.rb +7 -0
  11. data/example/app/output_objects/person_output_object.rb +37 -11
  12. data/example/app/output_objects/post_output_object.rb +0 -4
  13. data/example/app/output_objects/reporting_post_output.rb +18 -0
  14. data/example/bin/rspec +29 -0
  15. data/example/spec/requests/people/create_spec.rb +3 -2
  16. data/example/spec/requests/people/index_spec.rb +1 -1
  17. data/lib/sober_swag/compiler/path.rb +3 -1
  18. data/lib/sober_swag/compiler.rb +58 -12
  19. data/lib/sober_swag/controller/route.rb +44 -8
  20. data/lib/sober_swag/controller.rb +18 -5
  21. data/lib/sober_swag/input_object.rb +1 -0
  22. data/lib/sober_swag/output_object/field_syntax.rb +2 -0
  23. data/lib/sober_swag/reporting/compiler.rb +39 -0
  24. data/lib/sober_swag/reporting/input/base.rb +11 -0
  25. data/lib/sober_swag/reporting/input/bool.rb +19 -0
  26. data/lib/sober_swag/reporting/input/converting/bool.rb +24 -0
  27. data/lib/sober_swag/reporting/input/converting/date.rb +30 -0
  28. data/lib/sober_swag/reporting/input/converting/date_time.rb +28 -0
  29. data/lib/sober_swag/reporting/input/converting/decimal.rb +24 -0
  30. data/lib/sober_swag/reporting/input/converting/integer.rb +19 -0
  31. data/lib/sober_swag/reporting/input/converting.rb +16 -0
  32. data/lib/sober_swag/reporting/input/defer.rb +29 -0
  33. data/lib/sober_swag/reporting/input/described.rb +38 -0
  34. data/lib/sober_swag/reporting/input/dictionary.rb +37 -0
  35. data/lib/sober_swag/reporting/input/either.rb +51 -0
  36. data/lib/sober_swag/reporting/input/enum.rb +44 -0
  37. data/lib/sober_swag/reporting/input/format.rb +39 -0
  38. data/lib/sober_swag/reporting/input/in_range.rb +61 -0
  39. data/lib/sober_swag/reporting/input/interface.rb +113 -0
  40. data/lib/sober_swag/reporting/input/list.rb +44 -0
  41. data/lib/sober_swag/reporting/input/mapped.rb +36 -0
  42. data/lib/sober_swag/reporting/input/merge_objects.rb +72 -0
  43. data/lib/sober_swag/reporting/input/multiple_of.rb +36 -0
  44. data/lib/sober_swag/reporting/input/null.rb +34 -0
  45. data/lib/sober_swag/reporting/input/number.rb +19 -0
  46. data/lib/sober_swag/reporting/input/object/property.rb +53 -0
  47. data/lib/sober_swag/reporting/input/object.rb +100 -0
  48. data/lib/sober_swag/reporting/input/pattern.rb +46 -0
  49. data/lib/sober_swag/reporting/input/referenced.rb +38 -0
  50. data/lib/sober_swag/reporting/input/struct.rb +272 -0
  51. data/lib/sober_swag/reporting/input/text.rb +42 -0
  52. data/lib/sober_swag/reporting/input.rb +56 -0
  53. data/lib/sober_swag/reporting/invalid_schema_error.rb +21 -0
  54. data/lib/sober_swag/reporting/output/base.rb +25 -0
  55. data/lib/sober_swag/reporting/output/bool.rb +25 -0
  56. data/lib/sober_swag/reporting/output/defer.rb +69 -0
  57. data/lib/sober_swag/reporting/output/described.rb +42 -0
  58. data/lib/sober_swag/reporting/output/dictionary.rb +46 -0
  59. data/lib/sober_swag/reporting/output/enum.rb +47 -0
  60. data/lib/sober_swag/reporting/output/in_range.rb +64 -0
  61. data/lib/sober_swag/reporting/output/interface.rb +98 -0
  62. data/lib/sober_swag/reporting/output/list.rb +54 -0
  63. data/lib/sober_swag/reporting/output/merge_objects.rb +97 -0
  64. data/lib/sober_swag/reporting/output/null.rb +25 -0
  65. data/lib/sober_swag/reporting/output/number.rb +25 -0
  66. data/lib/sober_swag/reporting/output/object/property.rb +45 -0
  67. data/lib/sober_swag/reporting/output/object.rb +54 -0
  68. data/lib/sober_swag/reporting/output/partitioned.rb +77 -0
  69. data/lib/sober_swag/reporting/output/pattern.rb +50 -0
  70. data/lib/sober_swag/reporting/output/referenced.rb +42 -0
  71. data/lib/sober_swag/reporting/output/struct.rb +287 -0
  72. data/lib/sober_swag/reporting/output/text.rb +25 -0
  73. data/lib/sober_swag/reporting/output/via_map.rb +67 -0
  74. data/lib/sober_swag/reporting/output/viewed.rb +72 -0
  75. data/lib/sober_swag/reporting/output.rb +56 -0
  76. data/lib/sober_swag/reporting/report/base.rb +57 -0
  77. data/lib/sober_swag/reporting/report/either.rb +36 -0
  78. data/lib/sober_swag/reporting/report/error.rb +15 -0
  79. data/lib/sober_swag/reporting/report/list.rb +28 -0
  80. data/lib/sober_swag/reporting/report/merged_object.rb +25 -0
  81. data/lib/sober_swag/reporting/report/object.rb +29 -0
  82. data/lib/sober_swag/reporting/report/output.rb +14 -0
  83. data/lib/sober_swag/reporting/report/value.rb +28 -0
  84. data/lib/sober_swag/reporting/report.rb +16 -0
  85. data/lib/sober_swag/reporting.rb +11 -0
  86. data/lib/sober_swag/version.rb +1 -1
  87. data/lib/sober_swag.rb +1 -0
  88. metadata +69 -2
@@ -0,0 +1,56 @@
1
+ module SoberSwag
2
+ module Reporting
3
+ ##
4
+ # Reporting outputs.
5
+ #
6
+ # These outputs can tell you what their acceptable views are.
7
+ module Output
8
+ autoload(:Base, 'sober_swag/reporting/output/base')
9
+ autoload(:Bool, 'sober_swag/reporting/output/bool')
10
+ autoload(:Defer, 'sober_swag/reporting/output/defer')
11
+ autoload(:Described, 'sober_swag/reporting/output/described')
12
+ autoload(:Dictionary, 'sober_swag/reporting/output/dictionary')
13
+ autoload(:InRange, 'sober_swag/reporting/output/in_range')
14
+ autoload(:Interface, 'sober_swag/reporting/output/interface')
15
+ autoload(:List, 'sober_swag/reporting/output/list')
16
+ autoload(:MergeObjects, 'sober_swag/reporting/output/merge_objects')
17
+ autoload(:Null, 'sober_swag/reporting/output/null')
18
+ autoload(:Number, 'sober_swag/reporting/output/number')
19
+ autoload(:Enum, 'sober_swag/reporting/output/enum')
20
+ autoload(:Object, 'sober_swag/reporting/output/object')
21
+ autoload(:Partitioned, 'sober_swag/reporting/output/partitioned')
22
+ autoload(:Pattern, 'sober_swag/reporting/output/pattern')
23
+ autoload(:Referenced, 'sober_swag/reporting/output/referenced')
24
+ autoload(:Struct, 'sober_swag/reporting/output/struct')
25
+ autoload(:Text, 'sober_swag/reporting/output/text')
26
+ autoload(:ViaMap, 'sober_swag/reporting/output/via_map')
27
+ autoload(:Viewed, 'sober_swag/reporting/output/viewed')
28
+
29
+ class << self
30
+ ##
31
+ # @return [SoberSwag::Reporting::Output::Bool]
32
+ def bool
33
+ Bool.new
34
+ end
35
+
36
+ ##
37
+ # @return [SoberSwag::Reporting::Output::Number]
38
+ def number
39
+ Number.new
40
+ end
41
+
42
+ ##
43
+ # @return [SoberSwag::Reporting::Output::Text]
44
+ def text
45
+ Text.new
46
+ end
47
+
48
+ ##
49
+ # @return [SoberSwag::Reporting::Output::Null]
50
+ def null
51
+ Null.new
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,57 @@
1
+ module SoberSwag
2
+ module Reporting
3
+ module Report
4
+ ##
5
+ # Base class for SoberSwag reports.
6
+ #
7
+ # These reports are what make these serializers and parsers *reporting*: they provide errors.
8
+ # For outputs, these are errors encountered during serialization, IE,
9
+ # places where we lied about what type we were going to serialize.
10
+ # This is mostly used for testing.
11
+ #
12
+ # For parsers, these are encountered during *parsing*.
13
+ # This can be easily converted into a hash of JSON path objects to individual errors,
14
+ # enabling developers to more easily see what's gone wrong.
15
+ class Base
16
+ ##
17
+ # @return [Array<[String]>]
18
+ # An array of error paths and error components, in the form of:
19
+ #
20
+ # ```ruby
21
+ # [
22
+ # 'foo.bar: was bad',
23
+ # 'foo.bar: was even worse'
24
+ # ]
25
+ # ```
26
+ def full_errors
27
+ each_error.map do |k, v|
28
+ [k, v].reject(&:blank?).join(': ')
29
+ end
30
+ end
31
+
32
+ ##
33
+ # Get a hash where each key is a JSON path, and each value is an array of errors for that path.
34
+ # @return [Hash<String,Array<String>>] hash of JSON path to errors
35
+ def path_hash
36
+ Hash.new { |h, k| h[k] = [] }.tap do |hash|
37
+ each_error do |k, v|
38
+ hash["$#{k}"] << v
39
+ end
40
+ end
41
+ end
42
+
43
+ ##
44
+ # @overload each_error() { |path, val| nil }
45
+ # Yields each error to the block.
46
+ # @yield [path, val] the JSON path to the error, and an error string
47
+ # @yieldparam [String, String]
48
+ # @overload each_error()
49
+ # @return [Enumerable<String, String>] an enum of two values: error keys and error values.
50
+ # Note: the same key can potentially occur more than once!
51
+ def each_error
52
+ return enum_for(:each_error) unless block_given?
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,36 @@
1
+ module SoberSwag
2
+ module Reporting
3
+ module Report
4
+ ##
5
+ # Models either one set of errors or another.
6
+ # Will enumerate them in order with #each_error
7
+ class Either < Base
8
+ def initialize(lhs, rhs)
9
+ @lhs = lhs
10
+ @rhs = rhs
11
+ end
12
+
13
+ ##
14
+ # @return [Base] left reports
15
+ attr_reader :lhs
16
+ ##
17
+ # @return [Base] right reports
18
+ attr_reader :rhs
19
+
20
+ # rubocop:disable Style/ExplicitBlockArgument
21
+ def each_error
22
+ return enum_for(:each_error) unless block_given?
23
+
24
+ lhs.each_error do |key, value|
25
+ yield key, value
26
+ end
27
+
28
+ rhs.each_error do |key, value|
29
+ yield key, value
30
+ end
31
+ end
32
+ # rubocop:enable Style/ExplicitBlockArgument
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,15 @@
1
+ module SoberSwag
2
+ module Reporting
3
+ module Report
4
+ ##
5
+ # Exception thrown when used with {Reporting::Input::Interface#call!}.
6
+ class Error < StandardError
7
+ def initialize(report)
8
+ @report = report
9
+ end
10
+
11
+ attr_reader :report
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,28 @@
1
+ module SoberSwag
2
+ module Reporting
3
+ module Report
4
+ ##
5
+ # Report errors that arose while parsing a list.
6
+ class List < Base
7
+ ##
8
+ # @param element [Hash<Int, Base>] a hash of bad element indices to bad
9
+ # element values
10
+ def initialize(elements)
11
+ @elements = elements
12
+ end
13
+
14
+ attr_reader :elements
15
+
16
+ def each_error
17
+ return enum_for(:each_error) unless block_given?
18
+
19
+ elements.each do |k, v|
20
+ v.each_error do |nested, err|
21
+ yield ["[#{k}]", nested].reject(&:nil?).join(''), err
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,25 @@
1
+ module SoberSwag
2
+ module Reporting
3
+ module Report
4
+ ##
5
+ # Report on problems with a merged object.
6
+ class MergedObject < Base
7
+ def initialize(parent, child)
8
+ @parent = parent
9
+ @child = child
10
+ end
11
+
12
+ attr_reader :parent, :child
13
+
14
+ def each_error
15
+ return enum_for(:each_error) unless block_given?
16
+
17
+ # rubocop:disable Style/ExplicitBlockArgument
18
+ parent.each_error { |k, v| yield k, v }
19
+ child.each_error { |k, v| yield k, v }
20
+ # rubocop:enable Style/ExplicitBlockArgument
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,29 @@
1
+ module SoberSwag
2
+ module Reporting
3
+ module Report
4
+ ##
5
+ # Report on problems with an object.
6
+ class Object < Base
7
+ ##
8
+ # @param problems [Hash<Symbol, Report::Base>] the problems with each value.
9
+ def initialize(problems)
10
+ @problems = problems
11
+ end
12
+
13
+ ##
14
+ # @return [Hash] the hash being reported on
15
+ attr_reader :problems
16
+
17
+ def each_error
18
+ return enum_for(:each_error) unless block_given?
19
+
20
+ problems.each do |k, v|
21
+ v.each_error do |nested, err|
22
+ yield [".#{k}", nested].reject(&:nil?).join(''), err
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,14 @@
1
+ module SoberSwag
2
+ module Reporting
3
+ module Report
4
+ ##
5
+ # Output suitable to serialize an instance of {SoberSwag::Reporting::Report::Base} to
6
+ # a nice key-value thing.
7
+ Output = SoberSwag::Reporting::Output::Dictionary.of(
8
+ SoberSwag::Reporting::Output::List.new(
9
+ SoberSwag::Reporting::Output.text
10
+ )
11
+ ).via_map(&:path_hash)
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,28 @@
1
+ module SoberSwag
2
+ module Reporting
3
+ module Report
4
+ ##
5
+ # Report for a single value.
6
+ # Basically a wrapper around an array of strings.
7
+ class Value < Base
8
+ ##
9
+ # @param problems [Array<String>] problems with it
10
+ def initialize(problems)
11
+ @problems = problems
12
+ end
13
+
14
+ ##
15
+ # @return [Array<String>] the problems the value had
16
+ attr_reader :problems
17
+
18
+ def each_error
19
+ return enum_for(:each_error) unless block_given?
20
+
21
+ problems.each do |problem|
22
+ yield nil, problem
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,16 @@
1
+ module SoberSwag
2
+ module Reporting
3
+ ##
4
+ # Namespace modules for the various "reporters," or things that provide error handling.
5
+ module Report
6
+ autoload :Base, 'sober_swag/reporting/report/base'
7
+ autoload :Either, 'sober_swag/reporting/report/either'
8
+ autoload :Error, 'sober_swag/reporting/report/error'
9
+ autoload :Object, 'sober_swag/reporting/report/object'
10
+ autoload :Output, 'sober_swag/reporting/report/output'
11
+ autoload :MergedObject, 'sober_swag/reporting/report/merged_object'
12
+ autoload :Value, 'sober_swag/reporting/report/value'
13
+ autoload :List, 'sober_swag/reporting/report/list'
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,11 @@
1
+ module SoberSwag
2
+ ##
3
+ # A new module for parsers with better error reporting.
4
+ module Reporting
5
+ autoload :Input, 'sober_swag/reporting/input'
6
+ autoload :Report, 'sober_swag/reporting/report'
7
+ autoload :Output, 'sober_swag/reporting/output'
8
+ autoload :Compiler, 'sober_swag/reporting/compiler'
9
+ autoload :InvalidSchemaError, 'sober_swag/reporting/invalid_schema_error'
10
+ end
11
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SoberSwag
4
- VERSION = '0.21.0'
4
+ VERSION = '0.24.0'
5
5
  end
data/lib/sober_swag.rb CHANGED
@@ -24,6 +24,7 @@ module SoberSwag
24
24
  autoload :InputObject, 'sober_swag/input_object'
25
25
  autoload :Server, 'sober_swag/server'
26
26
  autoload :Type, 'sober_swag/type'
27
+ autoload :Reporting, 'sober_swag/reporting'
27
28
 
28
29
  ##
29
30
  # Define a struct of something.
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sober_swag
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.21.0
4
+ version: 0.24.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Anthony Super
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-09-02 00:00:00.000000000 Z
11
+ date: 2022-05-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -193,6 +193,7 @@ files:
193
193
  - bin/console
194
194
  - bin/rspec
195
195
  - bin/setup
196
+ - docs/reporting.md
196
197
  - docs/serializers.md
197
198
  - example/.gitignore
198
199
  - example/.rspec
@@ -210,12 +211,15 @@ files:
210
211
  - example/app/models/concerns/.keep
211
212
  - example/app/models/person.rb
212
213
  - example/app/models/post.rb
214
+ - example/app/output_objects/identified_output.rb
213
215
  - example/app/output_objects/person_errors_output_object.rb
214
216
  - example/app/output_objects/person_output_object.rb
215
217
  - example/app/output_objects/post_output_object.rb
218
+ - example/app/output_objects/reporting_post_output.rb
216
219
  - example/bin/bundle
217
220
  - example/bin/rails
218
221
  - example/bin/rake
222
+ - example/bin/rspec
219
223
  - example/bin/setup
220
224
  - example/bin/spring
221
225
  - example/config.ru
@@ -283,6 +287,69 @@ files:
283
287
  - lib/sober_swag/output_object/field_syntax.rb
284
288
  - lib/sober_swag/output_object/view.rb
285
289
  - lib/sober_swag/parser.rb
290
+ - lib/sober_swag/reporting.rb
291
+ - lib/sober_swag/reporting/compiler.rb
292
+ - lib/sober_swag/reporting/input.rb
293
+ - lib/sober_swag/reporting/input/base.rb
294
+ - lib/sober_swag/reporting/input/bool.rb
295
+ - lib/sober_swag/reporting/input/converting.rb
296
+ - lib/sober_swag/reporting/input/converting/bool.rb
297
+ - lib/sober_swag/reporting/input/converting/date.rb
298
+ - lib/sober_swag/reporting/input/converting/date_time.rb
299
+ - lib/sober_swag/reporting/input/converting/decimal.rb
300
+ - lib/sober_swag/reporting/input/converting/integer.rb
301
+ - lib/sober_swag/reporting/input/defer.rb
302
+ - lib/sober_swag/reporting/input/described.rb
303
+ - lib/sober_swag/reporting/input/dictionary.rb
304
+ - lib/sober_swag/reporting/input/either.rb
305
+ - lib/sober_swag/reporting/input/enum.rb
306
+ - lib/sober_swag/reporting/input/format.rb
307
+ - lib/sober_swag/reporting/input/in_range.rb
308
+ - lib/sober_swag/reporting/input/interface.rb
309
+ - lib/sober_swag/reporting/input/list.rb
310
+ - lib/sober_swag/reporting/input/mapped.rb
311
+ - lib/sober_swag/reporting/input/merge_objects.rb
312
+ - lib/sober_swag/reporting/input/multiple_of.rb
313
+ - lib/sober_swag/reporting/input/null.rb
314
+ - lib/sober_swag/reporting/input/number.rb
315
+ - lib/sober_swag/reporting/input/object.rb
316
+ - lib/sober_swag/reporting/input/object/property.rb
317
+ - lib/sober_swag/reporting/input/pattern.rb
318
+ - lib/sober_swag/reporting/input/referenced.rb
319
+ - lib/sober_swag/reporting/input/struct.rb
320
+ - lib/sober_swag/reporting/input/text.rb
321
+ - lib/sober_swag/reporting/invalid_schema_error.rb
322
+ - lib/sober_swag/reporting/output.rb
323
+ - lib/sober_swag/reporting/output/base.rb
324
+ - lib/sober_swag/reporting/output/bool.rb
325
+ - lib/sober_swag/reporting/output/defer.rb
326
+ - lib/sober_swag/reporting/output/described.rb
327
+ - lib/sober_swag/reporting/output/dictionary.rb
328
+ - lib/sober_swag/reporting/output/enum.rb
329
+ - lib/sober_swag/reporting/output/in_range.rb
330
+ - lib/sober_swag/reporting/output/interface.rb
331
+ - lib/sober_swag/reporting/output/list.rb
332
+ - lib/sober_swag/reporting/output/merge_objects.rb
333
+ - lib/sober_swag/reporting/output/null.rb
334
+ - lib/sober_swag/reporting/output/number.rb
335
+ - lib/sober_swag/reporting/output/object.rb
336
+ - lib/sober_swag/reporting/output/object/property.rb
337
+ - lib/sober_swag/reporting/output/partitioned.rb
338
+ - lib/sober_swag/reporting/output/pattern.rb
339
+ - lib/sober_swag/reporting/output/referenced.rb
340
+ - lib/sober_swag/reporting/output/struct.rb
341
+ - lib/sober_swag/reporting/output/text.rb
342
+ - lib/sober_swag/reporting/output/via_map.rb
343
+ - lib/sober_swag/reporting/output/viewed.rb
344
+ - lib/sober_swag/reporting/report.rb
345
+ - lib/sober_swag/reporting/report/base.rb
346
+ - lib/sober_swag/reporting/report/either.rb
347
+ - lib/sober_swag/reporting/report/error.rb
348
+ - lib/sober_swag/reporting/report/list.rb
349
+ - lib/sober_swag/reporting/report/merged_object.rb
350
+ - lib/sober_swag/reporting/report/object.rb
351
+ - lib/sober_swag/reporting/report/output.rb
352
+ - lib/sober_swag/reporting/report/value.rb
286
353
  - lib/sober_swag/serializer.rb
287
354
  - lib/sober_swag/serializer/array.rb
288
355
  - lib/sober_swag/serializer/base.rb