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.
Files changed (148) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +3 -4
  3. data/CHANGELOG.md +19 -0
  4. data/LICENSE.md +2 -3
  5. data/README.md +87 -43
  6. data/docs/{glossary.md → Glossary.md} +84 -52
  7. data/jsi.gemspec +1 -1
  8. data/lib/jsi/base/mutability.rb +48 -0
  9. data/lib/jsi/base/node.rb +66 -52
  10. data/lib/jsi/base.rb +592 -176
  11. data/lib/jsi/jsi_coder.rb +4 -2
  12. data/lib/jsi/metaschema_node/bootstrap_schema.rb +118 -59
  13. data/lib/jsi/metaschema_node.rb +244 -154
  14. data/lib/jsi/ptr.rb +45 -17
  15. data/lib/jsi/ref.rb +197 -0
  16. data/lib/jsi/registry.rb +311 -0
  17. data/lib/jsi/schema/cxt/child_application.rb +35 -0
  18. data/lib/jsi/schema/cxt/inplace_application.rb +37 -0
  19. data/lib/jsi/schema/cxt.rb +80 -0
  20. data/lib/jsi/schema/dialect.rb +137 -0
  21. data/lib/jsi/schema/draft04.rb +113 -5
  22. data/lib/jsi/schema/draft06.rb +123 -5
  23. data/lib/jsi/schema/draft07.rb +157 -5
  24. data/lib/jsi/schema/draft202012.rb +303 -0
  25. data/lib/jsi/schema/dynamic_anchor_map.rb +63 -0
  26. data/lib/jsi/schema/element.rb +69 -0
  27. data/lib/jsi/schema/elements/anchor.rb +13 -0
  28. data/lib/jsi/schema/elements/array_validation.rb +82 -0
  29. data/lib/jsi/schema/elements/comment.rb +10 -0
  30. data/lib/jsi/schema/{validation → elements}/const.rb +11 -7
  31. data/lib/jsi/schema/elements/contains.rb +59 -0
  32. data/lib/jsi/schema/elements/contains_minmax.rb +91 -0
  33. data/lib/jsi/schema/elements/content_encoding.rb +10 -0
  34. data/lib/jsi/schema/elements/content_media_type.rb +10 -0
  35. data/lib/jsi/schema/elements/content_schema.rb +16 -0
  36. data/lib/jsi/schema/elements/default.rb +11 -0
  37. data/lib/jsi/schema/elements/definitions.rb +19 -0
  38. data/lib/jsi/schema/elements/dependencies.rb +99 -0
  39. data/lib/jsi/schema/elements/dependent_required.rb +49 -0
  40. data/lib/jsi/schema/elements/dependent_schemas.rb +69 -0
  41. data/lib/jsi/schema/elements/dynamic_ref.rb +69 -0
  42. data/lib/jsi/schema/elements/enum.rb +26 -0
  43. data/lib/jsi/schema/elements/examples.rb +10 -0
  44. data/lib/jsi/schema/elements/format.rb +10 -0
  45. data/lib/jsi/schema/elements/id.rb +30 -0
  46. data/lib/jsi/schema/elements/if_then_else.rb +82 -0
  47. data/lib/jsi/schema/elements/info_bool.rb +10 -0
  48. data/lib/jsi/schema/elements/info_string.rb +10 -0
  49. data/lib/jsi/schema/elements/items.rb +93 -0
  50. data/lib/jsi/schema/elements/items_prefixed.rb +96 -0
  51. data/lib/jsi/schema/elements/not.rb +31 -0
  52. data/lib/jsi/schema/elements/numeric.rb +137 -0
  53. data/lib/jsi/schema/elements/numeric_draft04.rb +77 -0
  54. data/lib/jsi/schema/elements/object_validation.rb +55 -0
  55. data/lib/jsi/schema/elements/pattern.rb +35 -0
  56. data/lib/jsi/schema/elements/properties.rb +145 -0
  57. data/lib/jsi/schema/elements/property_names.rb +48 -0
  58. data/lib/jsi/schema/elements/ref.rb +62 -0
  59. data/lib/jsi/schema/elements/required.rb +34 -0
  60. data/lib/jsi/schema/elements/self.rb +24 -0
  61. data/lib/jsi/schema/elements/some_of.rb +180 -0
  62. data/lib/jsi/schema/elements/string_validation.rb +57 -0
  63. data/lib/jsi/schema/elements/type.rb +43 -0
  64. data/lib/jsi/schema/elements/unevaluated_items.rb +54 -0
  65. data/lib/jsi/schema/elements/unevaluated_properties.rb +54 -0
  66. data/lib/jsi/schema/elements/xschema.rb +10 -0
  67. data/lib/jsi/schema/elements/xvocabulary.rb +10 -0
  68. data/lib/jsi/schema/elements.rb +101 -0
  69. data/lib/jsi/schema/issue.rb +3 -4
  70. data/lib/jsi/schema/schema_ancestor_node.rb +105 -52
  71. data/lib/jsi/schema/vocabulary.rb +36 -0
  72. data/lib/jsi/schema.rb +598 -383
  73. data/lib/jsi/schema_classes.rb +195 -141
  74. data/lib/jsi/schema_set.rb +85 -128
  75. data/lib/jsi/set.rb +23 -0
  76. data/lib/jsi/simple_wrap.rb +14 -17
  77. data/lib/jsi/struct.rb +57 -0
  78. data/lib/jsi/uri.rb +40 -0
  79. data/lib/jsi/util/private/memo_map.rb +9 -13
  80. data/lib/jsi/util/private.rb +59 -31
  81. data/lib/jsi/util/typelike.rb +19 -60
  82. data/lib/jsi/util.rb +53 -34
  83. data/lib/jsi/validation/error.rb +45 -2
  84. data/lib/jsi/validation/result.rb +121 -90
  85. data/lib/jsi/validation.rb +1 -6
  86. data/lib/jsi/version.rb +1 -1
  87. data/lib/jsi.rb +170 -36
  88. data/lib/schemas/json-schema.org/draft/2020-12/schema.rb +62 -0
  89. data/lib/schemas/json-schema.org/draft-04/schema.rb +60 -109
  90. data/lib/schemas/json-schema.org/draft-06/schema.rb +53 -108
  91. data/lib/schemas/json-schema.org/draft-07/schema.rb +63 -127
  92. data/readme.rb +4 -4
  93. data/{resources}/schemas/2020-12_strict.json +19 -0
  94. data/{resources}/schemas/json-schema.org/draft/2020-12/meta/applicator.json +48 -0
  95. data/{resources}/schemas/json-schema.org/draft/2020-12/meta/content.json +17 -0
  96. data/{resources}/schemas/json-schema.org/draft/2020-12/meta/core.json +51 -0
  97. data/{resources}/schemas/json-schema.org/draft/2020-12/meta/format-annotation.json +14 -0
  98. data/{resources}/schemas/json-schema.org/draft/2020-12/meta/format-assertion.json +14 -0
  99. data/{resources}/schemas/json-schema.org/draft/2020-12/meta/meta-data.json +37 -0
  100. data/{resources}/schemas/json-schema.org/draft/2020-12/meta/unevaluated.json +15 -0
  101. data/{resources}/schemas/json-schema.org/draft/2020-12/meta/validation.json +98 -0
  102. data/{resources}/schemas/json-schema.org/draft/2020-12/schema.json +58 -0
  103. metadata +73 -52
  104. data/lib/jsi/metaschema.rb +0 -6
  105. data/lib/jsi/schema/application/child_application/contains.rb +0 -25
  106. data/lib/jsi/schema/application/child_application/draft04.rb +0 -21
  107. data/lib/jsi/schema/application/child_application/draft06.rb +0 -28
  108. data/lib/jsi/schema/application/child_application/draft07.rb +0 -28
  109. data/lib/jsi/schema/application/child_application/items.rb +0 -18
  110. data/lib/jsi/schema/application/child_application/properties.rb +0 -25
  111. data/lib/jsi/schema/application/child_application.rb +0 -13
  112. data/lib/jsi/schema/application/draft04.rb +0 -8
  113. data/lib/jsi/schema/application/draft06.rb +0 -8
  114. data/lib/jsi/schema/application/draft07.rb +0 -8
  115. data/lib/jsi/schema/application/inplace_application/dependencies.rb +0 -28
  116. data/lib/jsi/schema/application/inplace_application/draft04.rb +0 -25
  117. data/lib/jsi/schema/application/inplace_application/draft06.rb +0 -26
  118. data/lib/jsi/schema/application/inplace_application/draft07.rb +0 -32
  119. data/lib/jsi/schema/application/inplace_application/ifthenelse.rb +0 -20
  120. data/lib/jsi/schema/application/inplace_application/ref.rb +0 -18
  121. data/lib/jsi/schema/application/inplace_application/someof.rb +0 -44
  122. data/lib/jsi/schema/application/inplace_application.rb +0 -14
  123. data/lib/jsi/schema/application.rb +0 -12
  124. data/lib/jsi/schema/ref.rb +0 -183
  125. data/lib/jsi/schema/validation/array.rb +0 -69
  126. data/lib/jsi/schema/validation/contains.rb +0 -25
  127. data/lib/jsi/schema/validation/dependencies.rb +0 -49
  128. data/lib/jsi/schema/validation/draft04/minmax.rb +0 -91
  129. data/lib/jsi/schema/validation/draft04.rb +0 -110
  130. data/lib/jsi/schema/validation/draft06.rb +0 -120
  131. data/lib/jsi/schema/validation/draft07.rb +0 -157
  132. data/lib/jsi/schema/validation/enum.rb +0 -25
  133. data/lib/jsi/schema/validation/ifthenelse.rb +0 -46
  134. data/lib/jsi/schema/validation/items.rb +0 -54
  135. data/lib/jsi/schema/validation/not.rb +0 -20
  136. data/lib/jsi/schema/validation/numeric.rb +0 -121
  137. data/lib/jsi/schema/validation/object.rb +0 -45
  138. data/lib/jsi/schema/validation/pattern.rb +0 -34
  139. data/lib/jsi/schema/validation/properties.rb +0 -101
  140. data/lib/jsi/schema/validation/property_names.rb +0 -32
  141. data/lib/jsi/schema/validation/ref.rb +0 -40
  142. data/lib/jsi/schema/validation/required.rb +0 -27
  143. data/lib/jsi/schema/validation/someof.rb +0 -90
  144. data/lib/jsi/schema/validation/string.rb +0 -47
  145. data/lib/jsi/schema/validation/type.rb +0 -49
  146. data/lib/jsi/schema/validation.rb +0 -49
  147. data/lib/jsi/schema_registry.rb +0 -190
  148. data/lib/jsi/util/private/attr_struct.rb +0 -130
@@ -1,13 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module JSI
4
- module Schema::Application::ChildApplication
5
- autoload :Draft04, 'jsi/schema/application/child_application/draft04'
6
- autoload :Draft06, 'jsi/schema/application/child_application/draft06'
7
- autoload :Draft07, 'jsi/schema/application/child_application/draft07'
8
-
9
- autoload :Items, 'jsi/schema/application/child_application/items'
10
- autoload :Contains, 'jsi/schema/application/child_application/contains'
11
- autoload :Properties, 'jsi/schema/application/child_application/properties'
12
- end
13
- end
@@ -1,8 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module JSI
4
- module Schema::Application::Draft04
5
- include Schema::Application::InplaceApplication::Draft04
6
- include Schema::Application::ChildApplication::Draft04
7
- end
8
- end
@@ -1,8 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module JSI
4
- module Schema::Application::Draft06
5
- include Schema::Application::InplaceApplication::Draft06
6
- include Schema::Application::ChildApplication::Draft06
7
- end
8
- end
@@ -1,8 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module JSI
4
- module Schema::Application::Draft07
5
- include Schema::Application::InplaceApplication::Draft07
6
- include Schema::Application::ChildApplication::Draft07
7
- end
8
- end
@@ -1,28 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module JSI
4
- module Schema::Application::InplaceApplication::Dependencies
5
- # @private
6
- def internal_applicate_dependencies(instance, visited_refs, &block)
7
- if keyword?('dependencies')
8
- value = schema_content['dependencies']
9
- # This keyword's value MUST be an object. Each property specifies a dependency. Each dependency
10
- # value MUST be an array or a valid JSON Schema.
11
- if value.respond_to?(:to_hash)
12
- value.each_pair do |property_name, dependency|
13
- if dependency.respond_to?(:to_ary)
14
- # noop: array-form dependencies has no inplace applicator schema
15
- else
16
- # If the dependency value is a subschema, and the dependency key is a
17
- # property in the instance, the entire instance must validate against
18
- # the dependency value.
19
- if instance.respond_to?(:to_hash) && instance.key?(property_name)
20
- subschema(['dependencies', property_name]).each_inplace_applicator_schema(instance, visited_refs: visited_refs, &block)
21
- end
22
- end
23
- end
24
- end
25
- end
26
- end
27
- end
28
- end
@@ -1,25 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module JSI
4
- module Schema::Application::InplaceApplication::Draft04
5
- include Schema::Application::InplaceApplication::Ref
6
- include Schema::Application::InplaceApplication::Dependencies
7
- include Schema::Application::InplaceApplication::SomeOf
8
-
9
- # @private
10
- def internal_inplace_applicate_keywords(instance, visited_refs, &block)
11
- internal_applicate_ref(instance, visited_refs, throw_done: true, &block)
12
-
13
- # self is the first applicator schema if $ref has not short-circuited it
14
- yield self
15
-
16
- # 5.4.5. dependencies
17
- internal_applicate_dependencies(instance, visited_refs, &block)
18
-
19
- # 5.5.3. allOf
20
- # 5.5.4. anyOf
21
- # 5.5.5. oneOf
22
- internal_applicate_someOf(instance, visited_refs, &block)
23
- end
24
- end
25
- end
@@ -1,26 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module JSI
4
- module Schema::Application::InplaceApplication::Draft06
5
- include Schema::Application::InplaceApplication::Ref
6
- include Schema::Application::InplaceApplication::Dependencies
7
- include Schema::Application::InplaceApplication::SomeOf
8
-
9
- # @private
10
- def internal_inplace_applicate_keywords(instance, visited_refs, &block)
11
- # json-schema 8. Schema references with $ref
12
- internal_applicate_ref(instance, visited_refs, throw_done: true, &block)
13
-
14
- # self is the first applicator schema if $ref has not short-circuited it
15
- yield self
16
-
17
- # json-schema-validation 6.21. dependencies
18
- internal_applicate_dependencies(instance, visited_refs, &block)
19
-
20
- # json-schema-validation 6.26. allOf
21
- # json-schema-validation 6.27. anyOf
22
- # json-schema-validation 6.28. oneOf
23
- internal_applicate_someOf(instance, visited_refs, &block)
24
- end
25
- end
26
- end
@@ -1,32 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module JSI
4
- module Schema::Application::InplaceApplication::Draft07
5
- include Schema::Application::InplaceApplication::Ref
6
- include Schema::Application::InplaceApplication::Dependencies
7
- include Schema::Application::InplaceApplication::IfThenElse
8
- include Schema::Application::InplaceApplication::SomeOf
9
-
10
- # @private
11
- def internal_inplace_applicate_keywords(instance, visited_refs, &block)
12
- # json-schema 8. Schema references with $ref
13
- internal_applicate_ref(instance, visited_refs, throw_done: true, &block)
14
-
15
- # self is the first applicator schema if $ref has not short-circuited it
16
- block.call(self)
17
-
18
- # 6.5.7. dependencies
19
- internal_applicate_dependencies(instance, visited_refs, &block)
20
-
21
- # 6.6.1. if
22
- # 6.6.2. then
23
- # 6.6.3. else
24
- internal_applicate_ifthenelse(instance, visited_refs, &block)
25
-
26
- # 6.7.1. allOf
27
- # 6.7.2. anyOf
28
- # 6.7.3. oneOf
29
- internal_applicate_someOf(instance, visited_refs, &block)
30
- end
31
- end
32
- end
@@ -1,20 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module JSI
4
- module Schema::Application::InplaceApplication::IfThenElse
5
- # @private
6
- def internal_applicate_ifthenelse(instance, visited_refs, &block)
7
- if keyword?('if')
8
- if subschema(['if']).instance_valid?(instance)
9
- if keyword?('then')
10
- subschema(['then']).each_inplace_applicator_schema(instance, visited_refs: visited_refs, &block)
11
- end
12
- else
13
- if keyword?('else')
14
- subschema(['else']).each_inplace_applicator_schema(instance, visited_refs: visited_refs, &block)
15
- end
16
- end
17
- end
18
- end
19
- end
20
- end
@@ -1,18 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module JSI
4
- module Schema::Application::InplaceApplication::Ref
5
- # @private
6
- def internal_applicate_ref(instance, visited_refs, throw_done: false, &block)
7
- if keyword?('$ref') && schema_content['$ref'].respond_to?(:to_str)
8
- ref = schema_ref
9
- unless visited_refs.include?(ref)
10
- ref.deref_schema.each_inplace_applicator_schema(instance, visited_refs: visited_refs + [ref], &block)
11
- if throw_done
12
- throw(:jsi_application_done)
13
- end
14
- end
15
- end
16
- end
17
- end
18
- end
@@ -1,44 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module JSI
4
- module Schema::Application::InplaceApplication::SomeOf
5
- # @private
6
- def internal_applicate_someOf(instance, visited_refs, &block)
7
- if keyword?('allOf') && schema_content['allOf'].respond_to?(:to_ary)
8
- schema_content['allOf'].each_index do |i|
9
- subschema(['allOf', i]).each_inplace_applicator_schema(instance, visited_refs: visited_refs, &block)
10
- end
11
- end
12
- if keyword?('anyOf') && schema_content['anyOf'].respond_to?(:to_ary)
13
- anyOf = schema_content['anyOf'].each_index.map { |i| subschema(['anyOf', i]) }
14
- validOf = anyOf.select { |schema| schema.instance_valid?(instance) }
15
- if !validOf.empty?
16
- applicators = validOf
17
- else
18
- # invalid application: if none of the anyOf were valid, we apply them all
19
- applicators = anyOf
20
- end
21
-
22
- applicators.each do |applicator|
23
- applicator.each_inplace_applicator_schema(instance, visited_refs: visited_refs, &block)
24
- end
25
- end
26
- if keyword?('oneOf') && schema_content['oneOf'].respond_to?(:to_ary)
27
- oneOf_idxs = schema_content['oneOf'].each_index
28
- subschema_idx_valid = Hash.new { |h, i| h[i] = subschema(['oneOf', i]).instance_valid?(instance) }
29
- # count up to 2 `oneOf` subschemas which `instance` validates against
30
- nvalid = oneOf_idxs.inject(0) { |n, i| n > 1 ? n : subschema_idx_valid[i] ? n + 1 : n }
31
- if nvalid == 1
32
- applicator_idxs = oneOf_idxs.select { |i| subschema_idx_valid[i] }
33
- else
34
- # invalid application: if none or multiple of the oneOf were valid, we apply them all
35
- applicator_idxs = oneOf_idxs
36
- end
37
-
38
- applicator_idxs.each do |i|
39
- subschema(['oneOf', i]).each_inplace_applicator_schema(instance, visited_refs: visited_refs, &block)
40
- end
41
- end
42
- end
43
- end
44
- end
@@ -1,14 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module JSI
4
- module Schema::Application::InplaceApplication
5
- autoload :Draft04, 'jsi/schema/application/inplace_application/draft04'
6
- autoload :Draft06, 'jsi/schema/application/inplace_application/draft06'
7
- autoload :Draft07, 'jsi/schema/application/inplace_application/draft07'
8
-
9
- autoload :Ref, 'jsi/schema/application/inplace_application/ref'
10
- autoload :SomeOf, 'jsi/schema/application/inplace_application/someof'
11
- autoload :IfThenElse, 'jsi/schema/application/inplace_application/ifthenelse'
12
- autoload :Dependencies, 'jsi/schema/application/inplace_application/dependencies'
13
- end
14
- end
@@ -1,12 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module JSI
4
- module Schema::Application
5
- autoload :InplaceApplication, 'jsi/schema/application/inplace_application'
6
- autoload :ChildApplication, 'jsi/schema/application/child_application'
7
-
8
- autoload :Draft04, 'jsi/schema/application/draft04'
9
- autoload :Draft06, 'jsi/schema/application/draft06'
10
- autoload :Draft07, 'jsi/schema/application/draft07'
11
- end
12
- end
@@ -1,183 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module JSI
4
- # A JSI::Schema::Ref is a reference to a schema identified by a URI, typically from
5
- # a `$ref` keyword of a schema.
6
- class Schema::Ref
7
- # @param ref [String] A reference URI - typically the `$ref` value of the ref_schema
8
- # @param ref_schema [JSI::Schema] A schema from which the reference originated.
9
- #
10
- # If the ref URI consists of only a fragment, it is resolved from the `ref_schema`'s
11
- # {Schema#schema_resource_root}. Otherwise the resource is found in the `ref_schema`'s
12
- # {SchemaAncestorNode#jsi_schema_registry #jsi_schema_registry} (and any fragment is resolved from there).
13
- # @param schema_registry [SchemaRegistry] The registry in which the resource this ref refers to will be found.
14
- # This should only be specified in the absence of a `ref_schema`.
15
- # If neither is specified, {JSI.schema_registry} is used.
16
- def initialize(ref, ref_schema: nil, schema_registry: nil)
17
- raise(ArgumentError, "ref is not a string") unless ref.respond_to?(:to_str)
18
- @ref = ref
19
- @ref_uri = Util.uri(ref)
20
- @ref_schema = ref_schema ? Schema.ensure_schema(ref_schema) : nil
21
- @schema_registry = schema_registry || (ref_schema ? ref_schema.jsi_schema_registry : JSI.schema_registry)
22
- @deref_schema = nil
23
- end
24
-
25
- # @return [String]
26
- attr_reader :ref
27
-
28
- # @return [Addressable::URI]
29
- attr_reader :ref_uri
30
-
31
- # @return [Schema, nil]
32
- attr_reader :ref_schema
33
-
34
- # @return [SchemaRegistry, nil]
35
- attr_reader(:schema_registry)
36
-
37
- # finds the schema this ref points to
38
- # @return [JSI::Schema]
39
- # @raise [JSI::Schema::NotASchemaError] when the thing this ref points to is not a schema
40
- # @raise [JSI::Schema::ReferenceError] when this reference cannot be resolved
41
- def deref_schema
42
- return @deref_schema if @deref_schema
43
-
44
- schema_resource_root = nil
45
- check_schema_resource_root = -> {
46
- unless schema_resource_root
47
- raise(Schema::ReferenceError, [
48
- "cannot find schema by ref: #{ref}",
49
- ("from: #{ref_schema.pretty_inspect.chomp}" if ref_schema),
50
- ].compact.join("\n"))
51
- end
52
- }
53
-
54
- ref_uri_nofrag = ref_uri.merge(fragment: nil).freeze
55
-
56
- if ref_uri_nofrag.empty?
57
- unless ref_schema
58
- raise(Schema::ReferenceError, [
59
- "cannot find schema by ref: #{ref}",
60
- "with no ref schema",
61
- ].join("\n"))
62
- end
63
-
64
- # the URI only consists of a fragment (or is empty).
65
- # for a fragment pointer, resolve using Schema#resource_root_subschema on the ref_schema.
66
- # for a fragment anchor, bootstrap does not support anchors; otherwise use the ref_schema's schema_resource_root.
67
- schema_resource_root = ref_schema.is_a?(MetaschemaNode::BootstrapSchema) ? nil : ref_schema.schema_resource_root
68
- resolve_fragment_ptr = ref_schema.method(:resource_root_subschema)
69
- else
70
- # find the schema_resource_root from the non-fragment URI. we will resolve any fragment, either pointer or anchor, from there.
71
-
72
- if ref_uri_nofrag.absolute?
73
- ref_abs_uri = ref_uri_nofrag
74
- elsif ref_schema && ref_schema.jsi_resource_ancestor_uri
75
- ref_abs_uri = ref_schema.jsi_resource_ancestor_uri.join(ref_uri_nofrag).freeze
76
- else
77
- ref_abs_uri = nil
78
- end
79
- if ref_abs_uri
80
- unless schema_registry
81
- raise(Schema::ReferenceError, [
82
- "could not resolve remote ref with no schema_registry specified",
83
- "ref URI: #{ref_uri.to_s}",
84
- ("from: #{ref_schema.pretty_inspect.chomp}" if ref_schema),
85
- ].compact.join("\n"))
86
- end
87
- schema_resource_root = schema_registry.find(ref_abs_uri)
88
- end
89
-
90
- unless schema_resource_root
91
- # HAX for how google does refs and ids
92
- if ref_schema && ref_schema.jsi_document.respond_to?(:to_hash) && ref_schema.jsi_document['schemas'].respond_to?(:to_hash)
93
- ref_schema.jsi_document['schemas'].each do |k, v|
94
- if Addressable::URI.parse(v['id']) == ref_uri_nofrag
95
- schema_resource_root = ref_schema.resource_root_subschema(['schemas', k])
96
- end
97
- end
98
- end
99
- end
100
-
101
- check_schema_resource_root.call
102
-
103
- if schema_resource_root.is_a?(Schema)
104
- resolve_fragment_ptr = schema_resource_root.method(:resource_root_subschema)
105
- else
106
- # Note: Schema#resource_root_subschema will reinstantiate nonschemas as schemas.
107
- # not implemented for remote refs when the schema_resource_root is not a schema.
108
- resolve_fragment_ptr = -> (ptr) { schema_resource_root.jsi_descendent_node(ptr) }
109
- end
110
- end
111
-
112
- fragment = ref_uri.fragment
113
-
114
- if fragment
115
- begin
116
- ptr_from_fragment = Ptr.from_fragment(fragment)
117
- rescue Ptr::PointerSyntaxError
118
- end
119
- end
120
-
121
- if ptr_from_fragment
122
- begin
123
- result_schema = resolve_fragment_ptr.call(ptr_from_fragment)
124
- rescue Ptr::ResolutionError
125
- raise(Schema::ReferenceError, [
126
- "could not resolve pointer: #{ptr_from_fragment.pointer.inspect}",
127
- ("from: #{ref_schema.pretty_inspect.chomp}" if ref_schema),
128
- ("in schema resource root: #{schema_resource_root.pretty_inspect.chomp}" if schema_resource_root),
129
- ].compact.join("\n"))
130
- end
131
- elsif fragment.nil?
132
- check_schema_resource_root.call
133
- result_schema = schema_resource_root
134
- else
135
- check_schema_resource_root.call
136
-
137
- # find an anchor that resembles the fragment
138
- result_schemas = schema_resource_root.jsi_anchor_subschemas(fragment)
139
-
140
- if result_schemas.size == 1
141
- result_schema = result_schemas.first
142
- elsif result_schemas.size == 0
143
- raise(Schema::ReferenceError, [
144
- "could not find schema by fragment: #{fragment.inspect}",
145
- "in schema resource root: #{schema_resource_root.pretty_inspect.chomp}",
146
- ].join("\n"))
147
- else
148
- raise(Schema::ReferenceError, [
149
- "found multiple schemas for plain name fragment #{fragment.inspect}:",
150
- *result_schemas.map { |s| s.pretty_inspect.chomp },
151
- ].join("\n"))
152
- end
153
- end
154
-
155
- Schema.ensure_schema(result_schema, msg: "object identified by uri #{ref} is not a schema:")
156
- return @deref_schema = result_schema
157
- end
158
-
159
- # @return [String]
160
- def inspect
161
- -%Q(\#<#{self.class.name} #{ref}>)
162
- end
163
-
164
- alias_method :to_s, :inspect
165
-
166
- # pretty-prints a representation of self to the given printer
167
- # @return [void]
168
- def pretty_print(q)
169
- q.text '#<'
170
- q.text self.class.name
171
- q.text ' '
172
- q.text ref
173
- q.text '>'
174
- end
175
-
176
- # see {Util::Private::FingerprintHash}
177
- # @api private
178
- def jsi_fingerprint
179
- {class: self.class, ref: ref, ref_schema: ref_schema}
180
- end
181
- include Util::FingerprintHash
182
- end
183
- end
@@ -1,69 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module JSI
4
- module Schema::Validation::ArrayLength
5
- # @private
6
- def internal_validate_maxItems(result_builder)
7
- if keyword?('maxItems')
8
- value = schema_content['maxItems']
9
- # The value of this keyword MUST be a non-negative integer.
10
- if internal_integer?(value) && value >= 0
11
- if result_builder.instance.respond_to?(:to_ary)
12
- # An array instance is valid against "maxItems" if its size is less than, or equal to, the value of this keyword.
13
- result_builder.validate(
14
- result_builder.instance.to_ary.size <= value,
15
- 'instance array size is greater than `maxItems` value',
16
- keyword: 'maxItems',
17
- )
18
- end
19
- else
20
- result_builder.schema_error('`maxItems` is not a non-negative integer', 'maxItems')
21
- end
22
- end
23
- end
24
-
25
- # @private
26
- def internal_validate_minItems(result_builder)
27
- if keyword?('minItems')
28
- value = schema_content['minItems']
29
- # The value of this keyword MUST be a non-negative integer.
30
- if internal_integer?(value) && value >= 0
31
- if result_builder.instance.respond_to?(:to_ary)
32
- # An array instance is valid against "minItems" if its size is greater than, or equal to, the value of this keyword.
33
- result_builder.validate(
34
- result_builder.instance.to_ary.size >= value,
35
- 'instance array size is less than `minItems` value',
36
- keyword: 'minItems',
37
- )
38
- end
39
- else
40
- result_builder.schema_error('`minItems` is not a non-negative integer', 'minItems')
41
- end
42
- end
43
- end
44
- end
45
- module Schema::Validation::UniqueItems
46
- # @private
47
- def internal_validate_uniqueItems(result_builder)
48
- if keyword?('uniqueItems')
49
- value = schema_content['uniqueItems']
50
- # The value of this keyword MUST be a boolean.
51
- if value == false
52
- # If this keyword has boolean value false, the instance validates successfully.
53
- # (noop)
54
- elsif value == true
55
- if result_builder.instance.respond_to?(:to_ary)
56
- # If it has boolean value true, the instance validates successfully if all of its elements are unique.
57
- result_builder.validate(
58
- result_builder.instance.uniq.size == result_builder.instance.size,
59
- "instance array items' uniqueness does not match `uniqueItems` value",
60
- keyword: 'uniqueItems',
61
- )
62
- end
63
- else
64
- result_builder.schema_error('`uniqueItems` is not a boolean', 'uniqueItems')
65
- end
66
- end
67
- end
68
- end
69
- end
@@ -1,25 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module JSI
4
- module Schema::Validation::Contains
5
- # @private
6
- def internal_validate_contains(result_builder)
7
- if keyword?('contains')
8
- # An array instance is valid against "contains" if at least one of its elements is valid against
9
- # the given schema.
10
- if result_builder.instance.respond_to?(:to_ary)
11
- results = {}
12
- result_builder.instance.each_index do |i|
13
- results[i] = result_builder.child_subschema_validate(i, ['contains'])
14
- end
15
- result_builder.validate(
16
- results.values.any?(&:valid?),
17
- 'instance array does not contain any items valid against `contains` schema value',
18
- keyword: 'contains',
19
- results: results.values,
20
- )
21
- end
22
- end
23
- end
24
- end
25
- end
@@ -1,49 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module JSI
4
- module Schema::Validation::Dependencies
5
- # @private
6
- def internal_validate_dependencies(result_builder)
7
- if keyword?('dependencies')
8
- value = schema_content['dependencies']
9
- # This keyword's value MUST be an object. Each property specifies a dependency. Each dependency
10
- # value MUST be an array or a valid JSON Schema.
11
- if value.respond_to?(:to_hash)
12
- value.each_pair do |property_name, dependency|
13
- if dependency.respond_to?(:to_ary)
14
- # If the dependency value is an array, each element in the array, if
15
- # any, MUST be a string, and MUST be unique. If the dependency key is
16
- # a property in the instance, each of the items in the dependency value
17
- # must be a property that exists in the instance.
18
- if result_builder.instance.respond_to?(:to_hash) && result_builder.instance.key?(property_name)
19
- missing_required = dependency.reject { |name| result_builder.instance.key?(name) }
20
- # TODO include property_name / missing dependent required property names in the validation error
21
- result_builder.validate(
22
- missing_required.empty?,
23
- 'instance object does not contain all dependent required property names specified by `dependencies` value',
24
- keyword: 'dependencies',
25
- )
26
- end
27
- else
28
- # If the dependency value is a subschema, and the dependency key is a
29
- # property in the instance, the entire instance must validate against
30
- # the dependency value.
31
- if result_builder.instance.respond_to?(:to_hash) && result_builder.instance.key?(property_name)
32
- dependency_result = result_builder.inplace_subschema_validate(['dependencies', property_name])
33
- # TODO include property_name in the validation error
34
- result_builder.validate(
35
- dependency_result.valid?,
36
- 'instance object is not valid against the schema corresponding to a matched property name specified by `dependencies` value',
37
- keyword: 'dependencies',
38
- results: [dependency_result],
39
- )
40
- end
41
- end
42
- end
43
- else
44
- result_builder.schema_error('`dependencies` is not an object', 'dependencies')
45
- end
46
- end
47
- end
48
- end
49
- end