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,190 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module JSI
4
- class SchemaRegistry
5
- # an exception raised when an attempt is made to register a resource using a URI which is already
6
- # registered with another resource
7
- class Collision < StandardError
8
- end
9
-
10
- # an exception raised when an attempt is made to access (register or find) a resource of the
11
- # registry using a URI which is not absolute (it is a relative URI or it contains a fragment)
12
- class NonAbsoluteURI < StandardError
13
- end
14
-
15
- # an exception raised when a URI we are looking for has not been registered
16
- class ResourceNotFound < StandardError
17
- attr_accessor :uri
18
- end
19
-
20
- def initialize
21
- @resources = {}
22
- @autoload_uris = {}
23
- @resources_mutex = Mutex.new
24
- end
25
-
26
- # registers the given resource and/or schema resources it contains in the registry.
27
- #
28
- # each descendent node of the resource (including the resource itself) is registered if it is a schema
29
- # that has an absolute URI (generally defined by the '$id' keyword).
30
- #
31
- # the given resource itself will be registered, whether or not it is a schema, if it is the root
32
- # of its document and was instantiated with the option `uri` specified.
33
- #
34
- # @param resource [JSI::Base] a JSI containing resources to register
35
- # @return [void]
36
- def register(resource)
37
- unless resource.is_a?(JSI::Base)
38
- raise(ArgumentError, "resource must be a JSI::Base. got: #{resource.pretty_inspect.chomp}")
39
- end
40
- unless resource.is_a?(JSI::Schema) || resource.jsi_ptr.root?
41
- # unsure, should this be allowed? the given JSI is not a "resource" as we define it, but
42
- # if this check is removed it will just register any resources (schemas) below the given JSI.
43
- raise(ArgumentError, "undefined behavior: registration of a JSI which is not a schema and is not at the root of a document")
44
- end
45
-
46
- # allow for registration of resources at the root of a document whether or not they are schemas.
47
- # jsi_schema_base_uri at the root comes from the `uri` parameter to new_jsi / new_schema.
48
- if resource.jsi_schema_base_uri && resource.jsi_ptr.root?
49
- register_single(resource.jsi_schema_base_uri, resource)
50
- end
51
-
52
- resource.jsi_each_descendent_node do |node|
53
- if node.is_a?(JSI::Schema) && node.schema_absolute_uri
54
- register_single(node.schema_absolute_uri, node)
55
- end
56
- end
57
-
58
- nil
59
- end
60
-
61
- # takes a URI identifying a resource to be loaded by the given block
62
- # when a reference to the URI is followed.
63
- #
64
- # for example:
65
- #
66
- # JSI.schema_registry.autoload_uri('http://example.com/schema.json') do
67
- # JSI.new_schema({
68
- # '$schema' => 'http://json-schema.org/draft-07/schema#',
69
- # '$id' => 'http://example.com/schema.json',
70
- # 'title' => 'my schema',
71
- # })
72
- # end
73
- #
74
- # the block would normally load JSON from the filesystem or similar.
75
- #
76
- # @param uri [Addressable::URI]
77
- # @yieldreturn [JSI::Base] a JSI instance containing the resource identified by the given uri
78
- # @return [void]
79
- def autoload_uri(uri, &block)
80
- uri = ensure_uri_absolute(uri)
81
- mutating
82
- unless block
83
- raise(ArgumentError, ["#{SchemaRegistry}#autoload_uri must be invoked with a block", "URI: #{uri}"].join("\n"))
84
- end
85
- if @autoload_uris.key?(uri)
86
- raise(Collision, ["already registered URI for autoload", "URI: #{uri}", "loader: #{@autoload_uris[uri]}"].join("\n"))
87
- end
88
- @autoload_uris[uri] = block
89
- nil
90
- end
91
-
92
- # @param uri [Addressable::URI, #to_str]
93
- # @return [JSI::Base]
94
- # @raise [JSI::SchemaRegistry::ResourceNotFound]
95
- def find(uri)
96
- uri = ensure_uri_absolute(uri)
97
- if @autoload_uris.key?(uri)
98
- autoloaded = @autoload_uris[uri].call
99
- register(autoloaded)
100
- @autoload_uris.delete(uri)
101
- end
102
- if !@resources.key?(uri)
103
- if autoloaded
104
- msg = [
105
- "URI #{uri} was registered with autoload_uri but the result did not contain a resource with that URI.",
106
- "the resource resulting from autoload_uri was:",
107
- autoloaded.pretty_inspect.chomp,
108
- ]
109
- else
110
- msg = ["URI #{uri} is not registered. registered URIs:", *(@resources.keys | @autoload_uris.keys)]
111
- end
112
- raise(ResourceNotFound.new(msg.join("\n")).tap { |e| e.uri = uri })
113
- end
114
- @resources[uri]
115
- end
116
-
117
- def inspect
118
- [
119
- '#<JSI::SchemaRegistry',
120
- *[['autoload', @autoload_uris.keys], ['resources', @resources.keys]].map do |label, uris|
121
- [
122
- " #{label} (#{uris.size})#{uris.empty? ? "" : ":"}",
123
- *uris.map do |uri|
124
- " #{uri}"
125
- end,
126
- ]
127
- end.inject([], &:+),
128
- '>',
129
- ].join("\n").freeze
130
- end
131
-
132
- alias_method :to_s, :inspect
133
-
134
- def dup
135
- self.class.new.tap do |reg|
136
- @resources.each do |uri, resource|
137
- reg.register_single(uri, resource)
138
- end
139
- @autoload_uris.each do |uri, autoload|
140
- reg.autoload_uri(uri, &autoload)
141
- end
142
- end
143
- end
144
-
145
- def freeze
146
- @resources.freeze
147
- @autoload_uris.freeze
148
- @resources_mutex = nil
149
- super
150
- end
151
-
152
- protected
153
- # @param uri [Addressable::URI]
154
- # @param resource [JSI::Base]
155
- # @return [void]
156
- def register_single(uri, resource)
157
- mutating
158
- @resources_mutex.synchronize do
159
- ensure_uri_absolute(uri)
160
- if @resources.key?(uri)
161
- if @resources[uri] != resource
162
- raise(Collision, "URI collision on #{uri}.\nexisting:\n#{@resources[uri].pretty_inspect.chomp}\nnew:\n#{resource.pretty_inspect.chomp}")
163
- end
164
- else
165
- @resources[uri] = resource
166
- end
167
- end
168
- nil
169
- end
170
-
171
- private
172
-
173
- def ensure_uri_absolute(uri)
174
- uri = Util.uri(uri)
175
- if uri.fragment
176
- raise(NonAbsoluteURI, "#{self.class} only registers absolute URIs. cannot access URI with fragment: #{uri}")
177
- end
178
- if uri.relative?
179
- raise(NonAbsoluteURI, "#{self.class} only registers absolute URIs. cannot access relative URI: #{uri}")
180
- end
181
- uri
182
- end
183
-
184
- def mutating
185
- if frozen?
186
- raise(FrozenError, "cannot modify frozen #{self.class}")
187
- end
188
- end
189
- end
190
- end
@@ -1,130 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module JSI
4
- module Util::Private
5
- # like a Struct, but stores all the attributes in one @attributes Hash, instead of individual instance
6
- # variables for each attribute.
7
- # this tends to be easier to work with and more flexible. keys which are symbols are converted to strings.
8
- class AttrStruct
9
- class AttrStructError < StandardError
10
- end
11
-
12
- class UndefinedAttributeKey < AttrStructError
13
- end
14
-
15
- class << self
16
- # creates a AttrStruct subclass with the given attribute keys.
17
- # @param attribute_keys [Enumerable<String, Symbol>]
18
- def subclass(*attribute_keys)
19
- bad = attribute_keys.reject { |key| key.respond_to?(:to_str) || key.is_a?(Symbol) }
20
- unless bad.empty?
21
- raise ArgumentError, "attribute keys must be String or Symbol; got keys: #{bad.map(&:inspect).join(', ')}"
22
- end
23
- attribute_keys = attribute_keys.map { |key| convert_key(key) }
24
-
25
- all_attribute_keys = (self.attribute_keys + attribute_keys).freeze
26
-
27
- Class.new(self).tap do |klass|
28
- klass.define_singleton_method(:attribute_keys) { all_attribute_keys }
29
-
30
- attribute_keys.each do |attribute_key|
31
- # reader
32
- klass.send(:define_method, attribute_key) do
33
- @attributes[attribute_key]
34
- end
35
-
36
- # writer
37
- klass.send(:define_method, "#{attribute_key}=") do |value|
38
- @attributes[attribute_key] = value
39
- end
40
- end
41
- end
42
- end
43
-
44
- alias_method :[], :subclass
45
-
46
- # the attribute keys defined for this class
47
- # @return [Set<String>]
48
- def attribute_keys
49
- # empty for AttrStruct itself; redefined on each subclass
50
- Util::Private::EMPTY_SET
51
- end
52
-
53
- # returns a frozen string, given a string or symbol.
54
- # returns anything else as-is for the caller to handle.
55
- # @api private
56
- def convert_key(key)
57
- # TODO use Symbol#name when available on supported rubies
58
- key.is_a?(Symbol) ? key.to_s.freeze : key.frozen? ? key : key.is_a?(String) ? key.dup.freeze : key
59
- end
60
- end
61
-
62
- def initialize(attributes = {})
63
- unless attributes.respond_to?(:to_hash)
64
- raise(TypeError, "expected attributes to be a Hash; got: #{attributes.inspect}")
65
- end
66
- @attributes = {}
67
- attributes.to_hash.each do |k, v|
68
- @attributes[self.class.convert_key(k)] = v
69
- end
70
- bad = @attributes.keys.reject { |k| attribute_keys.include?(k) }
71
- unless bad.empty?
72
- raise UndefinedAttributeKey, "undefined attribute keys: #{bad.map(&:inspect).join(', ')}"
73
- end
74
- end
75
-
76
- def [](key)
77
- @attributes[key.is_a?(Symbol) ? key.to_s : key]
78
- end
79
-
80
- def []=(key, value)
81
- key = self.class.convert_key(key)
82
- unless attribute_keys.include?(key)
83
- raise UndefinedAttributeKey, "undefined attribute key: #{key.inspect}"
84
- end
85
- @attributes[key] = value
86
- end
87
-
88
- # @return [String]
89
- def inspect
90
- -"\#<#{self.class.name}#{@attributes.map { |k, v| " #{k}: #{v.inspect}" }.join(',')}>"
91
- end
92
-
93
- alias_method :to_s, :inspect
94
-
95
- # pretty-prints a representation of self to the given printer
96
- # @return [void]
97
- def pretty_print(q)
98
- q.text '#<'
99
- q.text self.class.name
100
- q.group_sub {
101
- q.nest(2) {
102
- q.breakable(@attributes.empty? ? '' : ' ')
103
- q.seplist(@attributes, nil, :each_pair) { |k, v|
104
- q.group {
105
- q.text k
106
- q.text ': '
107
- q.pp v
108
- }
109
- }
110
- }
111
- }
112
- q.breakable ''
113
- q.text '>'
114
- end
115
-
116
- # (see AttrStruct.attribute_keys)
117
- def attribute_keys
118
- self.class.attribute_keys
119
- end
120
-
121
- include FingerprintHash
122
-
123
- # see {Util::Private::FingerprintHash}
124
- # @api private
125
- def jsi_fingerprint
126
- {class: self.class, attributes: @attributes}
127
- end
128
- end
129
- end
130
- end