jsi-dev 0.0.8 → 0.0.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 +4 -4
- data/.yardopts +3 -4
- data/CHANGELOG.md +19 -0
- data/LICENSE.md +2 -3
- data/README.md +87 -43
- data/docs/{glossary.md → Glossary.md} +84 -52
- data/jsi.gemspec +1 -1
- data/lib/jsi/base/mutability.rb +48 -0
- data/lib/jsi/base/node.rb +66 -52
- data/lib/jsi/base.rb +592 -176
- data/lib/jsi/jsi_coder.rb +4 -2
- data/lib/jsi/metaschema_node/bootstrap_schema.rb +118 -59
- data/lib/jsi/metaschema_node.rb +244 -154
- data/lib/jsi/ptr.rb +45 -17
- data/lib/jsi/ref.rb +197 -0
- data/lib/jsi/registry.rb +311 -0
- data/lib/jsi/schema/cxt/child_application.rb +35 -0
- data/lib/jsi/schema/cxt/inplace_application.rb +37 -0
- data/lib/jsi/schema/cxt.rb +80 -0
- data/lib/jsi/schema/dialect.rb +137 -0
- data/lib/jsi/schema/draft04.rb +113 -5
- data/lib/jsi/schema/draft06.rb +123 -5
- data/lib/jsi/schema/draft07.rb +157 -5
- data/lib/jsi/schema/draft202012.rb +303 -0
- data/lib/jsi/schema/dynamic_anchor_map.rb +63 -0
- data/lib/jsi/schema/element.rb +69 -0
- data/lib/jsi/schema/elements/anchor.rb +13 -0
- data/lib/jsi/schema/elements/array_validation.rb +82 -0
- data/lib/jsi/schema/elements/comment.rb +10 -0
- data/lib/jsi/schema/{validation → elements}/const.rb +11 -7
- data/lib/jsi/schema/elements/contains.rb +59 -0
- data/lib/jsi/schema/elements/contains_minmax.rb +91 -0
- data/lib/jsi/schema/elements/content_encoding.rb +10 -0
- data/lib/jsi/schema/elements/content_media_type.rb +10 -0
- data/lib/jsi/schema/elements/content_schema.rb +16 -0
- data/lib/jsi/schema/elements/default.rb +11 -0
- data/lib/jsi/schema/elements/definitions.rb +19 -0
- data/lib/jsi/schema/elements/dependencies.rb +99 -0
- data/lib/jsi/schema/elements/dependent_required.rb +49 -0
- data/lib/jsi/schema/elements/dependent_schemas.rb +69 -0
- data/lib/jsi/schema/elements/dynamic_ref.rb +69 -0
- data/lib/jsi/schema/elements/enum.rb +26 -0
- data/lib/jsi/schema/elements/examples.rb +10 -0
- data/lib/jsi/schema/elements/format.rb +10 -0
- data/lib/jsi/schema/elements/id.rb +30 -0
- data/lib/jsi/schema/elements/if_then_else.rb +82 -0
- data/lib/jsi/schema/elements/info_bool.rb +10 -0
- data/lib/jsi/schema/elements/info_string.rb +10 -0
- data/lib/jsi/schema/elements/items.rb +93 -0
- data/lib/jsi/schema/elements/items_prefixed.rb +96 -0
- data/lib/jsi/schema/elements/not.rb +31 -0
- data/lib/jsi/schema/elements/numeric.rb +137 -0
- data/lib/jsi/schema/elements/numeric_draft04.rb +77 -0
- data/lib/jsi/schema/elements/object_validation.rb +55 -0
- data/lib/jsi/schema/elements/pattern.rb +35 -0
- data/lib/jsi/schema/elements/properties.rb +145 -0
- data/lib/jsi/schema/elements/property_names.rb +48 -0
- data/lib/jsi/schema/elements/ref.rb +62 -0
- data/lib/jsi/schema/elements/required.rb +34 -0
- data/lib/jsi/schema/elements/self.rb +24 -0
- data/lib/jsi/schema/elements/some_of.rb +180 -0
- data/lib/jsi/schema/elements/string_validation.rb +57 -0
- data/lib/jsi/schema/elements/type.rb +43 -0
- data/lib/jsi/schema/elements/unevaluated_items.rb +54 -0
- data/lib/jsi/schema/elements/unevaluated_properties.rb +54 -0
- data/lib/jsi/schema/elements/xschema.rb +10 -0
- data/lib/jsi/schema/elements/xvocabulary.rb +10 -0
- data/lib/jsi/schema/elements.rb +101 -0
- data/lib/jsi/schema/issue.rb +3 -4
- data/lib/jsi/schema/schema_ancestor_node.rb +105 -52
- data/lib/jsi/schema/vocabulary.rb +36 -0
- data/lib/jsi/schema.rb +598 -383
- data/lib/jsi/schema_classes.rb +195 -141
- data/lib/jsi/schema_set.rb +85 -128
- data/lib/jsi/set.rb +23 -0
- data/lib/jsi/simple_wrap.rb +14 -17
- data/lib/jsi/struct.rb +57 -0
- data/lib/jsi/uri.rb +40 -0
- data/lib/jsi/util/private/memo_map.rb +9 -13
- data/lib/jsi/util/private.rb +59 -31
- data/lib/jsi/util/typelike.rb +19 -60
- data/lib/jsi/util.rb +53 -34
- data/lib/jsi/validation/error.rb +45 -2
- data/lib/jsi/validation/result.rb +121 -90
- data/lib/jsi/validation.rb +1 -6
- data/lib/jsi/version.rb +1 -1
- data/lib/jsi.rb +170 -36
- data/lib/schemas/json-schema.org/draft/2020-12/schema.rb +62 -0
- data/lib/schemas/json-schema.org/draft-04/schema.rb +60 -109
- data/lib/schemas/json-schema.org/draft-06/schema.rb +53 -108
- data/lib/schemas/json-schema.org/draft-07/schema.rb +63 -127
- data/readme.rb +4 -4
- data/{resources}/schemas/2020-12_strict.json +19 -0
- data/{resources}/schemas/json-schema.org/draft/2020-12/meta/applicator.json +48 -0
- data/{resources}/schemas/json-schema.org/draft/2020-12/meta/content.json +17 -0
- data/{resources}/schemas/json-schema.org/draft/2020-12/meta/core.json +51 -0
- data/{resources}/schemas/json-schema.org/draft/2020-12/meta/format-annotation.json +14 -0
- data/{resources}/schemas/json-schema.org/draft/2020-12/meta/format-assertion.json +14 -0
- data/{resources}/schemas/json-schema.org/draft/2020-12/meta/meta-data.json +37 -0
- data/{resources}/schemas/json-schema.org/draft/2020-12/meta/unevaluated.json +15 -0
- data/{resources}/schemas/json-schema.org/draft/2020-12/meta/validation.json +98 -0
- data/{resources}/schemas/json-schema.org/draft/2020-12/schema.json +58 -0
- metadata +73 -52
- data/lib/jsi/metaschema.rb +0 -6
- data/lib/jsi/schema/application/child_application/contains.rb +0 -25
- data/lib/jsi/schema/application/child_application/draft04.rb +0 -21
- data/lib/jsi/schema/application/child_application/draft06.rb +0 -28
- data/lib/jsi/schema/application/child_application/draft07.rb +0 -28
- data/lib/jsi/schema/application/child_application/items.rb +0 -18
- data/lib/jsi/schema/application/child_application/properties.rb +0 -25
- data/lib/jsi/schema/application/child_application.rb +0 -13
- data/lib/jsi/schema/application/draft04.rb +0 -8
- data/lib/jsi/schema/application/draft06.rb +0 -8
- data/lib/jsi/schema/application/draft07.rb +0 -8
- data/lib/jsi/schema/application/inplace_application/dependencies.rb +0 -28
- data/lib/jsi/schema/application/inplace_application/draft04.rb +0 -25
- data/lib/jsi/schema/application/inplace_application/draft06.rb +0 -26
- data/lib/jsi/schema/application/inplace_application/draft07.rb +0 -32
- data/lib/jsi/schema/application/inplace_application/ifthenelse.rb +0 -20
- data/lib/jsi/schema/application/inplace_application/ref.rb +0 -18
- data/lib/jsi/schema/application/inplace_application/someof.rb +0 -44
- data/lib/jsi/schema/application/inplace_application.rb +0 -14
- data/lib/jsi/schema/application.rb +0 -12
- data/lib/jsi/schema/ref.rb +0 -183
- data/lib/jsi/schema/validation/array.rb +0 -69
- data/lib/jsi/schema/validation/contains.rb +0 -25
- data/lib/jsi/schema/validation/dependencies.rb +0 -49
- data/lib/jsi/schema/validation/draft04/minmax.rb +0 -91
- data/lib/jsi/schema/validation/draft04.rb +0 -110
- data/lib/jsi/schema/validation/draft06.rb +0 -120
- data/lib/jsi/schema/validation/draft07.rb +0 -157
- data/lib/jsi/schema/validation/enum.rb +0 -25
- data/lib/jsi/schema/validation/ifthenelse.rb +0 -46
- data/lib/jsi/schema/validation/items.rb +0 -54
- data/lib/jsi/schema/validation/not.rb +0 -20
- data/lib/jsi/schema/validation/numeric.rb +0 -121
- data/lib/jsi/schema/validation/object.rb +0 -45
- data/lib/jsi/schema/validation/pattern.rb +0 -34
- data/lib/jsi/schema/validation/properties.rb +0 -101
- data/lib/jsi/schema/validation/property_names.rb +0 -32
- data/lib/jsi/schema/validation/ref.rb +0 -40
- data/lib/jsi/schema/validation/required.rb +0 -27
- data/lib/jsi/schema/validation/someof.rb +0 -90
- data/lib/jsi/schema/validation/string.rb +0 -47
- data/lib/jsi/schema/validation/type.rb +0 -49
- data/lib/jsi/schema/validation.rb +0 -49
- data/lib/jsi/schema_registry.rb +0 -190
- data/lib/jsi/util/private/attr_struct.rb +0 -130
data/lib/jsi/util/typelike.rb
CHANGED
|
@@ -5,23 +5,24 @@ module JSI
|
|
|
5
5
|
#
|
|
6
6
|
# this module is intended to be internal to JSI. no guarantees or API promises
|
|
7
7
|
# are made for non-JSI classes including this module.
|
|
8
|
+
#
|
|
9
|
+
# @api private
|
|
8
10
|
module Util::Hashlike
|
|
11
|
+
include(Enumerable)
|
|
12
|
+
|
|
9
13
|
# safe methods which can be delegated to #to_hash (which the includer is assumed to have defined).
|
|
10
14
|
# 'safe' means, in this context, nondestructive - methods which do not modify the receiver.
|
|
11
15
|
|
|
12
16
|
# methods which do not need to access the value.
|
|
13
17
|
SAFE_KEY_ONLY_METHODS = %w(each_key empty? has_key? include? key? keys length member? size).map(&:freeze).freeze
|
|
14
|
-
SAFE_KEY_VALUE_METHODS = %w(< <= > >= any? assoc compact dig each_pair each_value fetch fetch_values has_value? invert key merge rassoc reject select to_h to_proc transform_values value? values values_at).map(&:freeze).freeze
|
|
15
|
-
DESTRUCTIVE_METHODS = %w(clear delete delete_if keep_if reject! replace select! shift).map(&:freeze).freeze
|
|
18
|
+
SAFE_KEY_VALUE_METHODS = %w(< <= > >= any? assoc compact dig each_pair each_value fetch fetch_values flatten has_value? invert key merge rassoc reject select filter to_h to_proc transform_values value? values values_at).map(&:freeze).freeze
|
|
19
|
+
DESTRUCTIVE_METHODS = %w(clear delete delete_if filter! flatten! keep_if reject! replace select! shift).map(&:freeze).freeze
|
|
16
20
|
# these return a modified copy
|
|
17
|
-
safe_modified_copy_methods = %w(compact)
|
|
18
|
-
# select and reject will return a modified copy but need the yielded block variable value from #[]
|
|
19
|
-
safe_kv_block_modified_copy_methods = %w(select reject)
|
|
21
|
+
safe_modified_copy_methods = %w(compact slice except)
|
|
20
22
|
SAFE_METHODS = SAFE_KEY_ONLY_METHODS | SAFE_KEY_VALUE_METHODS
|
|
21
23
|
custom_methods = %w(merge) # defined below
|
|
22
24
|
safe_to_hash_methods = SAFE_METHODS -
|
|
23
25
|
safe_modified_copy_methods -
|
|
24
|
-
safe_kv_block_modified_copy_methods -
|
|
25
26
|
custom_methods
|
|
26
27
|
safe_to_hash_methods.each do |method_name|
|
|
27
28
|
if Util::LAST_ARGUMENT_AS_KEYWORD_PARAMETERS
|
|
@@ -47,16 +48,6 @@ module JSI
|
|
|
47
48
|
end
|
|
48
49
|
end
|
|
49
50
|
end
|
|
50
|
-
safe_kv_block_modified_copy_methods.each do |method_name|
|
|
51
|
-
define_method(method_name) do |**kw, &b|
|
|
52
|
-
jsi_modified_copy do |object_to_modify|
|
|
53
|
-
responsive_object = object_to_modify.respond_to?(method_name) ? object_to_modify : object_to_modify.to_hash
|
|
54
|
-
responsive_object.public_send(method_name) do |k, _v|
|
|
55
|
-
b.call(k, self[k, **kw])
|
|
56
|
-
end
|
|
57
|
-
end
|
|
58
|
-
end
|
|
59
|
-
end
|
|
60
51
|
|
|
61
52
|
# like [Hash#update](https://ruby-doc.org/core/Hash.html#method-i-update)
|
|
62
53
|
# @param other [#to_hash] the other hash to update this hash from
|
|
@@ -91,34 +82,22 @@ module JSI
|
|
|
91
82
|
end
|
|
92
83
|
end
|
|
93
84
|
|
|
94
|
-
# basically the same #inspect as Hash, but has the class name and, if responsive,
|
|
95
|
-
# self's #jsi_object_group_text
|
|
96
|
-
# @return [String]
|
|
97
|
-
def inspect
|
|
98
|
-
object_group_str = (respond_to?(:jsi_object_group_text, true) ? jsi_object_group_text : [self.class]).join(' ')
|
|
99
|
-
-"\#{<#{object_group_str}>#{map { |k, v| " #{k.inspect} => #{v.inspect}" }.join(',')}}"
|
|
100
|
-
end
|
|
101
|
-
|
|
102
|
-
alias_method :to_s, :inspect
|
|
103
|
-
|
|
104
85
|
# pretty-prints a representation of this hashlike to the given printer
|
|
105
86
|
# @return [void]
|
|
106
87
|
def pretty_print(q)
|
|
107
88
|
object_group_str = (respond_to?(:jsi_object_group_text, true) ? jsi_object_group_text : [self.class]).join(' ')
|
|
108
89
|
q.text "\#{<#{object_group_str}>"
|
|
109
|
-
q.
|
|
90
|
+
q.group {
|
|
110
91
|
q.nest(2) {
|
|
111
92
|
q.breakable ' ' if !empty?
|
|
112
|
-
q.seplist(self
|
|
113
|
-
q.group {
|
|
93
|
+
q.seplist(self) { |k, v|
|
|
114
94
|
q.pp k
|
|
115
95
|
q.text ' => '
|
|
116
96
|
q.pp v
|
|
117
|
-
}
|
|
118
97
|
}
|
|
119
98
|
}
|
|
99
|
+
q.breakable('') if !empty?
|
|
120
100
|
}
|
|
121
|
-
q.breakable '' if !empty?
|
|
122
101
|
q.text '}'
|
|
123
102
|
end
|
|
124
103
|
end
|
|
@@ -127,24 +106,25 @@ module JSI
|
|
|
127
106
|
#
|
|
128
107
|
# this module is intended to be internal to JSI. no guarantees or API promises
|
|
129
108
|
# are made for non-JSI classes including this module.
|
|
109
|
+
#
|
|
110
|
+
# @api private
|
|
130
111
|
module Util::Arraylike
|
|
112
|
+
include(Enumerable)
|
|
113
|
+
|
|
131
114
|
# safe methods which can be delegated to #to_ary (which the includer is assumed to have defined).
|
|
132
115
|
# 'safe' means, in this context, nondestructive - methods which do not modify the receiver.
|
|
133
116
|
|
|
134
117
|
# methods which do not need to access the element.
|
|
135
118
|
SAFE_INDEX_ONLY_METHODS = %w(each_index empty? length size).map(&:freeze).freeze
|
|
136
119
|
# there are some ambiguous ones that are omitted, like #sort, #map / #collect.
|
|
137
|
-
SAFE_INDEX_ELEMENT_METHODS = %w(| & * + - <=> abbrev at bsearch bsearch_index combination compact count cycle dig drop drop_while fetch find_index first include? index join last pack permutation product reject repeated_combination repeated_permutation reverse reverse_each rindex rotate sample select shelljoin shuffle slice sort take take_while transpose uniq values_at zip).map(&:freeze).freeze
|
|
120
|
+
SAFE_INDEX_ELEMENT_METHODS = %w(| & * + - <=> abbrev at bsearch bsearch_index combination compact count cycle difference dig drop drop_while fetch find_index first include? index intersection intersect? join last pack permutation product reject repeated_combination repeated_permutation reverse reverse_each rindex rotate sample select shelljoin shuffle slice sort take take_while transpose union uniq values_at zip).map(&:freeze).freeze
|
|
138
121
|
DESTRUCTIVE_METHODS = %w(<< clear collect! compact! concat delete delete_at delete_if fill flatten! insert keep_if map! pop push reject! replace reverse! rotate! select! shift shuffle! slice! sort! sort_by! uniq! unshift).map(&:freeze).freeze
|
|
139
122
|
|
|
140
123
|
# methods (well, method) that returns a modified copy and doesn't need any handling of block variable(s)
|
|
141
124
|
safe_modified_copy_methods = %w(compact)
|
|
142
125
|
|
|
143
|
-
# methods that return a modified copy and do need handling of block variables
|
|
144
|
-
safe_el_block_methods = %w(reject select)
|
|
145
|
-
|
|
146
126
|
SAFE_METHODS = SAFE_INDEX_ONLY_METHODS | SAFE_INDEX_ELEMENT_METHODS
|
|
147
|
-
safe_to_ary_methods = SAFE_METHODS - safe_modified_copy_methods
|
|
127
|
+
safe_to_ary_methods = SAFE_METHODS - safe_modified_copy_methods
|
|
148
128
|
safe_to_ary_methods.each do |method_name|
|
|
149
129
|
if Util::LAST_ARGUMENT_AS_KEYWORD_PARAMETERS
|
|
150
130
|
define_method(method_name) { |*a, &b| to_ary.public_send(method_name, *a, &b) }
|
|
@@ -169,17 +149,6 @@ module JSI
|
|
|
169
149
|
end
|
|
170
150
|
end
|
|
171
151
|
end
|
|
172
|
-
safe_el_block_methods.each do |method_name|
|
|
173
|
-
define_method(method_name) do |**kw, &b|
|
|
174
|
-
jsi_modified_copy do |object_to_modify|
|
|
175
|
-
i = 0
|
|
176
|
-
responsive_object = object_to_modify.respond_to?(method_name) ? object_to_modify : object_to_modify.to_ary
|
|
177
|
-
responsive_object.public_send(method_name) do |_e|
|
|
178
|
-
b.call(self[i, **kw]).tap { i += 1 }
|
|
179
|
-
end
|
|
180
|
-
end
|
|
181
|
-
end
|
|
182
|
-
end
|
|
183
152
|
|
|
184
153
|
# see [Array#assoc](https://ruby-doc.org/core/Array.html#method-i-assoc)
|
|
185
154
|
def assoc(obj)
|
|
@@ -195,30 +164,20 @@ module JSI
|
|
|
195
164
|
detect { |e| e.respond_to?(:to_ary) and e[1] == obj }
|
|
196
165
|
end
|
|
197
166
|
|
|
198
|
-
# basically the same #inspect as Array, but has the class name and, if responsive,
|
|
199
|
-
# self's #jsi_object_group_text
|
|
200
|
-
# @return [String]
|
|
201
|
-
def inspect
|
|
202
|
-
object_group_str = (respond_to?(:jsi_object_group_text, true) ? jsi_object_group_text : [self.class]).join(' ')
|
|
203
|
-
-"\#[<#{object_group_str}>#{map { |e| ' ' + e.inspect }.join(',')}]"
|
|
204
|
-
end
|
|
205
|
-
|
|
206
|
-
alias_method :to_s, :inspect
|
|
207
|
-
|
|
208
167
|
# pretty-prints a representation of this arraylike to the given printer
|
|
209
168
|
# @return [void]
|
|
210
169
|
def pretty_print(q)
|
|
211
170
|
object_group_str = (respond_to?(:jsi_object_group_text, true) ? jsi_object_group_text : [self.class]).join(' ')
|
|
212
171
|
q.text "\#[<#{object_group_str}>"
|
|
213
|
-
q.
|
|
172
|
+
q.group {
|
|
214
173
|
q.nest(2) {
|
|
215
174
|
q.breakable ' ' if !empty?
|
|
216
|
-
q.seplist(self
|
|
175
|
+
q.seplist(self) { |e|
|
|
217
176
|
q.pp e
|
|
218
177
|
}
|
|
219
178
|
}
|
|
179
|
+
q.breakable('') if !empty?
|
|
220
180
|
}
|
|
221
|
-
q.breakable '' if !empty?
|
|
222
181
|
q.text ']'
|
|
223
182
|
end
|
|
224
183
|
end
|
data/lib/jsi/util.rb
CHANGED
|
@@ -1,10 +1,48 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require("delegate")
|
|
4
|
+
|
|
3
5
|
module JSI
|
|
4
6
|
# JSI::Util contains public utilities
|
|
5
7
|
module Util
|
|
6
8
|
autoload :Private, 'jsi/util/private'
|
|
7
9
|
|
|
10
|
+
# common methods of inspecting / pretty-printing
|
|
11
|
+
# @private (not in Util::Private due to dependency order)
|
|
12
|
+
module Pretty
|
|
13
|
+
# @return [String]
|
|
14
|
+
def inspect
|
|
15
|
+
out = String.new
|
|
16
|
+
PP.singleline_pp(self, out)
|
|
17
|
+
out.freeze
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# @return [String]
|
|
21
|
+
def to_s
|
|
22
|
+
inspect
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
private
|
|
26
|
+
|
|
27
|
+
def jsi_pp_object_group(q, pres = [self.class.name].freeze, empty: false)
|
|
28
|
+
q.text('#<')
|
|
29
|
+
pres.each_with_index do |pre, i|
|
|
30
|
+
q.text(' ') if i != 0
|
|
31
|
+
q.text(pre.to_s)
|
|
32
|
+
end
|
|
33
|
+
if block_given? && !empty
|
|
34
|
+
q.group do
|
|
35
|
+
q.nest(2) do
|
|
36
|
+
q.breakable(' ')
|
|
37
|
+
yield
|
|
38
|
+
end
|
|
39
|
+
q.breakable('')
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
q.text('>')
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
8
46
|
include Private
|
|
9
47
|
|
|
10
48
|
extend self
|
|
@@ -13,7 +51,7 @@ module JSI
|
|
|
13
51
|
autoload :Hashlike, 'jsi/util/typelike'
|
|
14
52
|
|
|
15
53
|
# yields the content of the given param `object`. for objects which have a #jsi_modified_copy
|
|
16
|
-
# method of their own (JSI::Base, JSI::
|
|
54
|
+
# method of their own (JSI::Base, JSI::MetaSchemaNode) that method is invoked with the given
|
|
17
55
|
# block. otherwise the given object itself is yielded.
|
|
18
56
|
#
|
|
19
57
|
# the given block must result in a modified copy of its block parameter
|
|
@@ -32,7 +70,7 @@ module JSI
|
|
|
32
70
|
|
|
33
71
|
# A structure like the given `object`, recursively coerced to JSON-compatible types.
|
|
34
72
|
#
|
|
35
|
-
# - Structures of Hash, Array, and
|
|
73
|
+
# - Structures of Hash, Array, and simple types of String/number/boolean/nil are returned as-is.
|
|
36
74
|
# - If the object responds to `#as_json`, that method is used, passing any given options.
|
|
37
75
|
# - If the object supports [implicit conversion](https://docs.ruby-lang.org/en/master/implicit_conversion_rdoc.html)
|
|
38
76
|
# with `#to_hash`, `#to_ary`, `#to_str`, or `#to_int`, that is used.
|
|
@@ -46,7 +84,7 @@ module JSI
|
|
|
46
84
|
type_err = proc { raise(TypeError, "cannot express object as json: #{object.pretty_inspect.chomp}") }
|
|
47
85
|
if object.respond_to?(:as_json)
|
|
48
86
|
options.empty? ? object.as_json : object.as_json(**options) # TODO remove eventually (keyword argument compatibility)
|
|
49
|
-
elsif object.is_a?(
|
|
87
|
+
elsif object.is_a?(URI)
|
|
50
88
|
object.to_s
|
|
51
89
|
elsif object.respond_to?(:to_hash) && (object_to_hash = object.to_hash).is_a?(Hash)
|
|
52
90
|
result = {}
|
|
@@ -67,7 +105,7 @@ module JSI
|
|
|
67
105
|
object
|
|
68
106
|
elsif object.is_a?(Symbol)
|
|
69
107
|
object.to_s
|
|
70
|
-
elsif object.is_a?(Set)
|
|
108
|
+
elsif object.is_a?(::Set)
|
|
71
109
|
as_json(object.to_a, **options)
|
|
72
110
|
elsif object.respond_to?(:to_str) && (object_to_str = object.to_str).is_a?(String)
|
|
73
111
|
object_to_str
|
|
@@ -85,10 +123,15 @@ module JSI
|
|
|
85
123
|
# - Otherwise, JSON is generated using {as_json} to coerce to compatible types.
|
|
86
124
|
# @return [String]
|
|
87
125
|
def to_json(object, options = {})
|
|
126
|
+
options_state = options.class.name =~ /\AJSON:.*:Generator::State\z/
|
|
88
127
|
if USE_TO_JSON_METHOD[object.class]
|
|
89
|
-
options.empty? ? object.to_json : object.to_json
|
|
128
|
+
(options_state || !options.empty?) ? object.to_json(options) : object.to_json # TODO remove eventually (keyword argument compatibility)
|
|
90
129
|
else
|
|
91
|
-
|
|
130
|
+
if options_state
|
|
131
|
+
JSON.generate(as_json(object), options)
|
|
132
|
+
else
|
|
133
|
+
JSON.generate(as_json(object, **options))
|
|
134
|
+
end
|
|
92
135
|
end
|
|
93
136
|
end
|
|
94
137
|
|
|
@@ -120,7 +163,7 @@ module JSI
|
|
|
120
163
|
end
|
|
121
164
|
|
|
122
165
|
def deep_stringify_symbol_keys(object)
|
|
123
|
-
if object.respond_to?(:to_hash) && !object.is_a?(
|
|
166
|
+
if object.respond_to?(:to_hash) && !object.is_a?(URI)
|
|
124
167
|
JSI::Util.modified_copy(object) do |hash|
|
|
125
168
|
out = {}
|
|
126
169
|
(hash.respond_to?(:each) ? hash : hash.to_hash).each do |k, v|
|
|
@@ -143,7 +186,9 @@ module JSI
|
|
|
143
186
|
# the given object is not modified.
|
|
144
187
|
def deep_to_frozen(object, not_implemented: nil)
|
|
145
188
|
dtf = proc { |o| deep_to_frozen(o, not_implemented: not_implemented) }
|
|
146
|
-
if object.
|
|
189
|
+
if object.is_a?(Delegator)
|
|
190
|
+
object.class.new(dtf[object.__getobj__]).freeze
|
|
191
|
+
elsif object.instance_of?(Hash)
|
|
147
192
|
out = {}
|
|
148
193
|
identical = object.frozen?
|
|
149
194
|
object.each do |k, v|
|
|
@@ -197,31 +242,5 @@ module JSI
|
|
|
197
242
|
end
|
|
198
243
|
end
|
|
199
244
|
end
|
|
200
|
-
|
|
201
|
-
# ensures the given param becomes a frozen Set of Modules.
|
|
202
|
-
# returns the param if it is already that, otherwise initializes and freezes such a Set.
|
|
203
|
-
#
|
|
204
|
-
# @param modules [Set, Enumerable] the object to ensure becomes a frozen Set of Modules
|
|
205
|
-
# @return [Set] frozen Set containing the given modules
|
|
206
|
-
# @raise [ArgumentError] when the modules param is not an Enumerable
|
|
207
|
-
# @raise [Schema::NotASchemaError] when the modules param contains objects which are not Schemas
|
|
208
|
-
def ensure_module_set(modules)
|
|
209
|
-
if modules.is_a?(Set) && modules.frozen?
|
|
210
|
-
set = modules
|
|
211
|
-
elsif modules.is_a?(Enumerable)
|
|
212
|
-
set = Set.new(modules).freeze
|
|
213
|
-
else
|
|
214
|
-
raise(TypeError, "not given an Enumerable of Modules")
|
|
215
|
-
end
|
|
216
|
-
not_modules = set.reject { |s| s.is_a?(Module) }
|
|
217
|
-
if !not_modules.empty?
|
|
218
|
-
raise(TypeError, [
|
|
219
|
-
"ensure_module_set given non-Module objects:",
|
|
220
|
-
*not_modules.map { |ns| ns.pretty_inspect.chomp },
|
|
221
|
-
].join("\n"))
|
|
222
|
-
end
|
|
223
|
-
|
|
224
|
-
set
|
|
225
|
-
end
|
|
226
245
|
end
|
|
227
246
|
end
|
data/lib/jsi/validation/error.rb
CHANGED
|
@@ -2,13 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
module JSI
|
|
4
4
|
module Validation
|
|
5
|
-
Error =
|
|
5
|
+
Error = Struct.subclass(*%i(
|
|
6
6
|
message
|
|
7
7
|
keyword
|
|
8
|
+
additional
|
|
8
9
|
schema
|
|
9
10
|
instance_ptr
|
|
10
11
|
instance_document
|
|
11
|
-
|
|
12
|
+
nested_errors
|
|
13
|
+
))
|
|
12
14
|
|
|
13
15
|
# a validation error of a schema instance against a schema
|
|
14
16
|
#
|
|
@@ -19,6 +21,9 @@ module JSI
|
|
|
19
21
|
# the keyword of the schema which failed to validate.
|
|
20
22
|
# this may be absent if the error is not from a schema keyword (i.e, `false` schema).
|
|
21
23
|
# @return [String]
|
|
24
|
+
# @!attribute additional
|
|
25
|
+
# additional contextual information about the error
|
|
26
|
+
# @return [Hash]
|
|
22
27
|
# @!attribute schema
|
|
23
28
|
# the schema against which the instance failed to validate
|
|
24
29
|
# @return [JSI::Schema]
|
|
@@ -28,7 +33,45 @@ module JSI
|
|
|
28
33
|
# @!attribute instance_document
|
|
29
34
|
# document containing the instance at instance_ptr
|
|
30
35
|
# @return [Object]
|
|
36
|
+
# @!attribute nested_errors
|
|
37
|
+
# @return [Set<Validation::Error>]
|
|
31
38
|
class Error
|
|
39
|
+
def initialize(attributes = {})
|
|
40
|
+
super
|
|
41
|
+
freeze
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# @yield [Validation::Error]
|
|
45
|
+
def each_validation_error(&block)
|
|
46
|
+
return(to_enum(__method__)) if !block_given?
|
|
47
|
+
nested_errors.each { |nested_error| nested_error.each_validation_error(&block) }
|
|
48
|
+
yield(self)
|
|
49
|
+
nil
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# @return [Object]
|
|
53
|
+
def instance
|
|
54
|
+
instance_ptr.evaluate(instance_document)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def pretty_print(q)
|
|
58
|
+
info = {
|
|
59
|
+
message: message,
|
|
60
|
+
instance: instance,
|
|
61
|
+
instance_ptr: instance_ptr,
|
|
62
|
+
keyword: keyword,
|
|
63
|
+
additional: additional,
|
|
64
|
+
'schema uri': schema.schema_uri || schema.jsi_ptr.uri,
|
|
65
|
+
nested_errors: nested_errors,
|
|
66
|
+
}
|
|
67
|
+
jsi_pp_object_group(q) do
|
|
68
|
+
q.seplist(info) do |k, v|
|
|
69
|
+
q.text(k.to_s)
|
|
70
|
+
q.text(': ')
|
|
71
|
+
q.pp(v)
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
32
75
|
end
|
|
33
76
|
end
|
|
34
77
|
end
|