jsi 0.7.0 → 0.8.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.yardopts +6 -1
- data/CHANGELOG.md +19 -0
- data/README.md +29 -20
- data/jsi.gemspec +2 -3
- data/lib/jsi/base/mutability.rb +44 -0
- data/lib/jsi/base/node.rb +199 -34
- data/lib/jsi/base.rb +412 -228
- data/lib/jsi/jsi_coder.rb +18 -16
- data/lib/jsi/metaschema_node/bootstrap_schema.rb +57 -23
- data/lib/jsi/metaschema_node.rb +138 -107
- data/lib/jsi/ptr.rb +59 -37
- data/lib/jsi/schema/application/child_application/draft04.rb +0 -1
- data/lib/jsi/schema/application/child_application/draft06.rb +0 -1
- data/lib/jsi/schema/application/child_application/draft07.rb +0 -1
- data/lib/jsi/schema/application/child_application.rb +0 -25
- data/lib/jsi/schema/application/inplace_application/draft04.rb +0 -1
- data/lib/jsi/schema/application/inplace_application/draft06.rb +0 -1
- data/lib/jsi/schema/application/inplace_application/draft07.rb +0 -1
- data/lib/jsi/schema/application/inplace_application/ref.rb +1 -1
- data/lib/jsi/schema/application/inplace_application/someof.rb +1 -1
- data/lib/jsi/schema/application/inplace_application.rb +0 -27
- data/lib/jsi/schema/draft04.rb +0 -1
- data/lib/jsi/schema/draft06.rb +0 -1
- data/lib/jsi/schema/draft07.rb +0 -1
- data/lib/jsi/schema/ref.rb +44 -18
- data/lib/jsi/schema/schema_ancestor_node.rb +65 -56
- data/lib/jsi/schema/validation/contains.rb +1 -1
- data/lib/jsi/schema/validation/draft04/minmax.rb +2 -0
- data/lib/jsi/schema/validation/draft04.rb +0 -2
- data/lib/jsi/schema/validation/draft06.rb +0 -2
- data/lib/jsi/schema/validation/draft07.rb +0 -2
- data/lib/jsi/schema/validation/items.rb +3 -3
- data/lib/jsi/schema/validation/pattern.rb +1 -1
- data/lib/jsi/schema/validation/properties.rb +4 -4
- data/lib/jsi/schema/validation/ref.rb +1 -1
- data/lib/jsi/schema/validation.rb +0 -2
- data/lib/jsi/schema.rb +408 -198
- data/lib/jsi/schema_classes.rb +196 -127
- data/lib/jsi/schema_registry.rb +66 -17
- data/lib/jsi/schema_set.rb +76 -30
- data/lib/jsi/simple_wrap.rb +2 -7
- data/lib/jsi/util/private/attr_struct.rb +28 -14
- data/lib/jsi/util/private/memo_map.rb +75 -0
- data/lib/jsi/util/private.rb +73 -92
- data/lib/jsi/util/typelike.rb +28 -28
- data/lib/jsi/util.rb +120 -36
- data/lib/jsi/validation/error.rb +4 -0
- data/lib/jsi/validation/result.rb +18 -32
- data/lib/jsi/version.rb +1 -1
- data/lib/jsi.rb +67 -25
- data/lib/schemas/json-schema.org/draft-04/schema.rb +159 -4
- data/lib/schemas/json-schema.org/draft-06/schema.rb +161 -4
- data/lib/schemas/json-schema.org/draft-07/schema.rb +188 -4
- data/readme.rb +1 -1
- metadata +19 -5
- data/lib/jsi/metaschema.rb +0 -6
- data/lib/jsi/schema/validation/core.rb +0 -39
@@ -4,9 +4,21 @@ module JSI
|
|
4
4
|
# a node in a document which may contain a schema somewhere within is extended with SchemaAncestorNode, for
|
5
5
|
# tracking things necessary for a schema to function correctly
|
6
6
|
module Schema::SchemaAncestorNode
|
7
|
+
if Util::LAST_ARGUMENT_AS_KEYWORD_PARAMETERS
|
8
|
+
def initialize(*)
|
9
|
+
super
|
10
|
+
jsi_schema_ancestor_node_initialize
|
11
|
+
end
|
12
|
+
else
|
13
|
+
def initialize(*, **)
|
14
|
+
super
|
15
|
+
jsi_schema_ancestor_node_initialize
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
7
19
|
# the base URI used to resolve the ids of schemas at or below this JSI.
|
8
20
|
# this is always an absolute URI (with no fragment).
|
9
|
-
#
|
21
|
+
# This may be the absolute schema URI of an ancestor schema or the URI from which the document was retrieved.
|
10
22
|
# @api private
|
11
23
|
# @return [Addressable::URI, nil]
|
12
24
|
attr_reader :jsi_schema_base_uri
|
@@ -14,25 +26,27 @@ module JSI
|
|
14
26
|
# resources which are ancestors of this JSI in the document. this does not include self.
|
15
27
|
# @api private
|
16
28
|
# @return [Array<JSI::Schema>]
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
29
|
+
attr_reader :jsi_schema_resource_ancestors
|
30
|
+
|
31
|
+
# See {SchemaSet#new_jsi} param `schema_registry`
|
32
|
+
# @return [SchemaRegistry]
|
33
|
+
attr_reader(:jsi_schema_registry)
|
21
34
|
|
22
35
|
# the URI of the resource containing this node.
|
23
36
|
# this is always an absolute URI (with no fragment).
|
24
|
-
#
|
37
|
+
# If this node is a schema with an id, this is its absolute URI; otherwise an ancestor resource's URI,
|
25
38
|
# or nil if not contained by a resource with a URI.
|
26
39
|
# @return [Addressable::URI, nil]
|
27
40
|
def jsi_resource_ancestor_uri
|
28
41
|
(is_a?(Schema) && schema_absolute_uri) || jsi_schema_base_uri
|
29
42
|
end
|
30
43
|
|
31
|
-
#
|
44
|
+
# The schema at or below this node with the given anchor.
|
45
|
+
# If no schema has that anchor (or multiple schemas do, incorrectly), nil.
|
32
46
|
#
|
33
47
|
# @return [JSI::Schema, nil]
|
34
48
|
def jsi_anchor_subschema(anchor)
|
35
|
-
subschemas =
|
49
|
+
subschemas = @anchor_subschemas_map[anchor: anchor]
|
36
50
|
if subschemas.size == 1
|
37
51
|
subschemas.first
|
38
52
|
else
|
@@ -40,74 +54,69 @@ module JSI
|
|
40
54
|
end
|
41
55
|
end
|
42
56
|
|
43
|
-
# schemas at or below node with the given anchor.
|
57
|
+
# All schemas at or below this node with the given anchor.
|
44
58
|
#
|
45
|
-
# @return [
|
59
|
+
# @return [Set<JSI::Schema>]
|
46
60
|
def jsi_anchor_subschemas(anchor)
|
47
|
-
|
61
|
+
@anchor_subschemas_map[anchor: anchor]
|
48
62
|
end
|
49
63
|
|
50
64
|
private
|
51
65
|
|
52
|
-
def
|
53
|
-
@
|
66
|
+
def jsi_schema_ancestor_node_initialize
|
67
|
+
@anchor_subschemas_map = jsi_memomap(&method(:jsi_anchor_subschemas_compute))
|
54
68
|
end
|
55
69
|
|
70
|
+
attr_writer :jsi_document
|
71
|
+
|
56
72
|
def jsi_ptr=(jsi_ptr)
|
57
|
-
raise(Bug, "jsi_ptr not #{Ptr}: #{jsi_ptr
|
73
|
+
#chkbug raise(Bug, "jsi_ptr not #{Ptr}: #{jsi_ptr}") unless jsi_ptr.is_a?(Ptr)
|
58
74
|
@jsi_ptr = jsi_ptr
|
59
75
|
end
|
60
76
|
|
61
77
|
def jsi_schema_base_uri=(jsi_schema_base_uri)
|
62
|
-
if jsi_schema_base_uri
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
unless @jsi_schema_base_uri.absolute? && !@jsi_schema_base_uri.fragment
|
68
|
-
raise(ArgumentError, "jsi_schema_base_uri must be an absolute URI with no fragment; got: #{jsi_schema_base_uri.inspect}")
|
69
|
-
end
|
70
|
-
else
|
71
|
-
@jsi_schema_base_uri = nil
|
72
|
-
end
|
78
|
+
#chkbug raise(Bug) if jsi_schema_base_uri && !jsi_schema_base_uri.is_a?(Addressable::URI)
|
79
|
+
#chkbug raise(Bug) if jsi_schema_base_uri && !jsi_schema_base_uri.absolute?
|
80
|
+
#chkbug raise(Bug) if jsi_schema_base_uri && jsi_schema_base_uri.fragment
|
81
|
+
|
82
|
+
@jsi_schema_base_uri = jsi_schema_base_uri
|
73
83
|
end
|
74
84
|
|
75
85
|
def jsi_schema_resource_ancestors=(jsi_schema_resource_ancestors)
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
end
|
98
|
-
|
99
|
-
@jsi_schema_resource_ancestors = jsi_schema_resource_ancestors.to_ary.freeze
|
100
|
-
else
|
101
|
-
@jsi_schema_resource_ancestors = Util::EMPTY_ARY
|
102
|
-
end
|
86
|
+
#chkbug raise(Bug) unless jsi_schema_resource_ancestors.respond_to?(:to_ary)
|
87
|
+
#chkbug jsi_schema_resource_ancestors.each { |a| Schema.ensure_schema(a) }
|
88
|
+
#chkbug # sanity check the ancestors are in order
|
89
|
+
#chkbug last_anc_ptr = nil
|
90
|
+
#chkbug jsi_schema_resource_ancestors.each do |anc|
|
91
|
+
#chkbug if last_anc_ptr.nil?
|
92
|
+
#chkbug # pass
|
93
|
+
#chkbug elsif last_anc_ptr == anc.jsi_ptr
|
94
|
+
#chkbug raise(Bug, "duplicate ancestors in #{jsi_schema_resource_ancestors.pretty_inspect}")
|
95
|
+
#chkbug elsif !last_anc_ptr.contains?(anc.jsi_ptr)
|
96
|
+
#chkbug raise(Bug, "ancestor ptr #{anc.jsi_ptr} not contained by previous: #{last_anc_ptr} in #{jsi_schema_resource_ancestors.pretty_inspect}")
|
97
|
+
#chkbug end
|
98
|
+
#chkbug if anc.jsi_ptr == jsi_ptr
|
99
|
+
#chkbug raise(Bug, "ancestor is self")
|
100
|
+
#chkbug elsif !anc.jsi_ptr.ancestor_of?(jsi_ptr)
|
101
|
+
#chkbug raise(Bug, "ancestor does not contain self")
|
102
|
+
#chkbug end
|
103
|
+
#chkbug last_anc_ptr = anc.jsi_ptr
|
104
|
+
#chkbug end
|
105
|
+
|
106
|
+
@jsi_schema_resource_ancestors = jsi_schema_resource_ancestors
|
103
107
|
end
|
104
108
|
|
105
|
-
|
106
|
-
|
109
|
+
attr_writer(:jsi_schema_registry)
|
110
|
+
|
111
|
+
def jsi_anchor_subschemas_compute(anchor: )
|
107
112
|
jsi_each_descendent_node.select do |node|
|
108
113
|
node.is_a?(Schema) && node.respond_to?(:anchor) && node.anchor == anchor
|
109
|
-
end.freeze
|
110
|
-
|
114
|
+
end.to_set.freeze
|
115
|
+
end
|
116
|
+
|
117
|
+
# @return [Util::MemoMap]
|
118
|
+
def jsi_memomap(**options, &block)
|
119
|
+
jsi_memomap_class.new(**options, &block)
|
111
120
|
end
|
112
121
|
end
|
113
122
|
end
|
@@ -10,7 +10,7 @@ module JSI
|
|
10
10
|
if result_builder.instance.respond_to?(:to_ary)
|
11
11
|
results = {}
|
12
12
|
result_builder.instance.each_index do |i|
|
13
|
-
results[i] = result_builder.child_subschema_validate(['contains']
|
13
|
+
results[i] = result_builder.child_subschema_validate(i, ['contains'])
|
14
14
|
end
|
15
15
|
result_builder.validate(
|
16
16
|
results.values.any?(&:valid?),
|
@@ -10,6 +10,7 @@ module JSI
|
|
10
10
|
unless [true, false].include?(value)
|
11
11
|
result_builder.schema_error('`exclusiveMaximum` is not true or false', 'exclusiveMaximum')
|
12
12
|
end
|
13
|
+
#> If "exclusiveMaximum" is present, "maximum" MUST also be present.
|
13
14
|
if !keyword?('maximum')
|
14
15
|
result_builder.schema_error('`exclusiveMaximum` has no effect without adjacent `maximum` keyword', 'exclusiveMaximum')
|
15
16
|
end
|
@@ -53,6 +54,7 @@ module JSI
|
|
53
54
|
unless [true, false].include?(value)
|
54
55
|
result_builder.schema_error('`exclusiveMinimum` is not true or false', 'exclusiveMinimum')
|
55
56
|
end
|
57
|
+
#> If "exclusiveMinimum" is present, "minimum" MUST also be present.
|
56
58
|
if !keyword?('minimum')
|
57
59
|
result_builder.schema_error('`exclusiveMinimum` has no effect without adjacent `minimum` keyword', 'exclusiveMinimum')
|
58
60
|
end
|
@@ -14,9 +14,9 @@ module JSI
|
|
14
14
|
results = {}
|
15
15
|
result_builder.instance.each_index do |i|
|
16
16
|
if i < value.size
|
17
|
-
results[i] = result_builder.child_subschema_validate(['items', i]
|
17
|
+
results[i] = result_builder.child_subschema_validate(i, ['items', i])
|
18
18
|
elsif keyword?('additionalItems')
|
19
|
-
results[i] = result_builder.child_subschema_validate(['additionalItems']
|
19
|
+
results[i] = result_builder.child_subschema_validate(i, ['additionalItems'])
|
20
20
|
end
|
21
21
|
end
|
22
22
|
result_builder.validate(
|
@@ -31,7 +31,7 @@ module JSI
|
|
31
31
|
# against that schema.
|
32
32
|
if result_builder.instance.respond_to?(:to_ary)
|
33
33
|
results = result_builder.instance.each_index.map do |i|
|
34
|
-
result_builder.child_subschema_validate(['items']
|
34
|
+
result_builder.child_subschema_validate(i, ['items'])
|
35
35
|
end
|
36
36
|
result_builder.validate(
|
37
37
|
results.all?(&:valid?),
|
@@ -22,7 +22,7 @@ module JSI
|
|
22
22
|
keyword: 'pattern',
|
23
23
|
)
|
24
24
|
rescue RegexpError => e
|
25
|
-
result_builder.schema_error("`pattern` is not a valid regular expression: #{e.message}", 'pattern')
|
25
|
+
result_builder.schema_error(-"`pattern` is not a valid regular expression: #{e.message}", 'pattern')
|
26
26
|
end
|
27
27
|
end
|
28
28
|
else
|
@@ -19,8 +19,8 @@ module JSI
|
|
19
19
|
if value.key?(property_name)
|
20
20
|
evaluated_property_names << property_name
|
21
21
|
results[property_name] = result_builder.child_subschema_validate(
|
22
|
+
property_name,
|
22
23
|
['properties', property_name],
|
23
|
-
[property_name],
|
24
24
|
)
|
25
25
|
end
|
26
26
|
end
|
@@ -54,8 +54,8 @@ module JSI
|
|
54
54
|
if value_property_pattern.respond_to?(:to_str) && Regexp.new(value_property_pattern).match(property_name.to_s)
|
55
55
|
evaluated_property_names << property_name
|
56
56
|
results[property_name] = result_builder.child_subschema_validate(
|
57
|
+
property_name,
|
57
58
|
['patternProperties', value_property_pattern],
|
58
|
-
[property_name],
|
59
59
|
)
|
60
60
|
end
|
61
61
|
rescue ::RegexpError
|
@@ -83,11 +83,11 @@ module JSI
|
|
83
83
|
result_builder.instance.keys.each do |property_name|
|
84
84
|
if !evaluated_property_names.include?(property_name)
|
85
85
|
results[property_name] = result_builder.child_subschema_validate(
|
86
|
+
property_name,
|
86
87
|
['additionalProperties'],
|
87
|
-
[property_name],
|
88
88
|
)
|
89
89
|
end
|
90
|
-
end
|
90
|
+
end
|
91
91
|
result_builder.validate(
|
92
92
|
results.values.all?(&:valid?),
|
93
93
|
'instance object additional properties are not all valid against `additionalProperties` schema value',
|
@@ -10,7 +10,7 @@ module JSI
|
|
10
10
|
value = schema_content['$ref']
|
11
11
|
|
12
12
|
if value.respond_to?(:to_str)
|
13
|
-
schema_ref =
|
13
|
+
schema_ref = self.schema_ref('$ref')
|
14
14
|
|
15
15
|
if result_builder.visited_refs.include?(schema_ref)
|
16
16
|
result_builder.schema_error('self-referential schema structure', '$ref')
|