jsi 0.6.0 → 0.8.0
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 +6 -1
 - data/CHANGELOG.md +33 -0
 - data/LICENSE.md +1 -1
 - data/README.md +29 -23
 - data/jsi.gemspec +29 -0
 - data/lib/jsi/base/mutability.rb +44 -0
 - data/lib/jsi/base/node.rb +348 -0
 - data/lib/jsi/base.rb +497 -339
 - data/lib/jsi/jsi_coder.rb +19 -17
 - data/lib/jsi/metaschema_node/bootstrap_schema.rb +61 -26
 - data/lib/jsi/metaschema_node.rb +161 -133
 - data/lib/jsi/ptr.rb +80 -47
 - data/lib/jsi/schema/application/child_application/contains.rb +11 -2
 - 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/items.rb +3 -3
 - data/lib/jsi/schema/application/child_application/properties.rb +3 -3
 - data/lib/jsi/schema/application/child_application.rb +0 -27
 - data/lib/jsi/schema/application/inplace_application/dependencies.rb +1 -1
 - 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/ifthenelse.rb +3 -3
 - data/lib/jsi/schema/application/inplace_application/ref.rb +2 -2
 - data/lib/jsi/schema/application/inplace_application/someof.rb +26 -11
 - data/lib/jsi/schema/application/inplace_application.rb +0 -32
 - 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 +46 -19
 - data/lib/jsi/schema/schema_ancestor_node.rb +69 -66
 - data/lib/jsi/schema/validation/array.rb +3 -3
 - data/lib/jsi/schema/validation/const.rb +1 -1
 - data/lib/jsi/schema/validation/contains.rb +2 -2
 - data/lib/jsi/schema/validation/dependencies.rb +1 -1
 - data/lib/jsi/schema/validation/draft04/minmax.rb +8 -6
 - 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/enum.rb +1 -1
 - data/lib/jsi/schema/validation/ifthenelse.rb +5 -5
 - data/lib/jsi/schema/validation/items.rb +7 -7
 - data/lib/jsi/schema/validation/not.rb +1 -1
 - data/lib/jsi/schema/validation/numeric.rb +5 -5
 - data/lib/jsi/schema/validation/object.rb +2 -2
 - data/lib/jsi/schema/validation/pattern.rb +2 -2
 - data/lib/jsi/schema/validation/properties.rb +7 -7
 - data/lib/jsi/schema/validation/property_names.rb +1 -1
 - data/lib/jsi/schema/validation/ref.rb +2 -2
 - data/lib/jsi/schema/validation/required.rb +1 -1
 - data/lib/jsi/schema/validation/someof.rb +3 -3
 - data/lib/jsi/schema/validation/string.rb +2 -2
 - data/lib/jsi/schema/validation/type.rb +1 -1
 - data/lib/jsi/schema/validation.rb +1 -3
 - data/lib/jsi/schema.rb +443 -226
 - data/lib/jsi/schema_classes.rb +241 -147
 - data/lib/jsi/schema_registry.rb +78 -19
 - data/lib/jsi/schema_set.rb +114 -28
 - data/lib/jsi/simple_wrap.rb +18 -4
 - data/lib/jsi/util/private/attr_struct.rb +141 -0
 - data/lib/jsi/util/private/memo_map.rb +75 -0
 - data/lib/jsi/util/private.rb +185 -0
 - data/lib/jsi/{typelike_modules.rb → util/typelike.rb} +79 -105
 - data/lib/jsi/util.rb +157 -153
 - 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 +65 -39
 - data/lib/schemas/json-schema.org/draft-04/schema.rb +160 -3
 - data/lib/schemas/json-schema.org/draft-06/schema.rb +162 -3
 - data/lib/schemas/json-schema.org/draft-07/schema.rb +189 -3
 - metadata +27 -11
 - data/lib/jsi/metaschema.rb +0 -7
 - data/lib/jsi/pathed_node.rb +0 -116
 - data/lib/jsi/schema/validation/core.rb +0 -39
 - data/lib/jsi/util/attr_struct.rb +0 -106
 
    
        data/lib/jsi/schema.rb
    CHANGED
    
    | 
         @@ -1,19 +1,24 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            # frozen_string_literal: true
         
     | 
| 
       2 
2 
     | 
    
         | 
| 
       3 
3 
     | 
    
         
             
            module JSI
         
     | 
| 
       4 
     | 
    
         
            -
              # JSI::Schema is a module which extends instances which represent JSON schemas.
         
     | 
| 
      
 4 
     | 
    
         
            +
              # JSI::Schema is a module which extends {JSI::Base} instances which represent JSON schemas.
         
     | 
| 
       5 
5 
     | 
    
         
             
              #
         
     | 
| 
       6 
     | 
    
         
            -
              #  
     | 
| 
       7 
     | 
    
         
            -
              #  
     | 
| 
      
 6 
     | 
    
         
            +
              # This module is included on the {Schema#jsi_schema_module JSI Schema module} of any schema
         
     | 
| 
      
 7 
     | 
    
         
            +
              # that describes other schemas, i.e. is a meta-schema (a {Schema::MetaSchema}).
         
     | 
| 
      
 8 
     | 
    
         
            +
              # Therefore, any JSI instance described by a schema which is a {Schema::MetaSchema} is
         
     | 
| 
      
 9 
     | 
    
         
            +
              # a schema and is extended by this module.
         
     | 
| 
      
 10 
     | 
    
         
            +
              #
         
     | 
| 
      
 11 
     | 
    
         
            +
              # The content of an instance which is a JSI::Schema (referred to in this context as schema_content) is
         
     | 
| 
      
 12 
     | 
    
         
            +
              # typically a Hash (JSON object) or a boolean.
         
     | 
| 
       8 
13 
     | 
    
         
             
              module Schema
         
     | 
| 
       9 
14 
     | 
    
         
             
                autoload :Application, 'jsi/schema/application'
         
     | 
| 
       10 
15 
     | 
    
         
             
                autoload :Validation, 'jsi/schema/validation'
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
       11 
17 
     | 
    
         
             
                autoload :Issue, 'jsi/schema/issue'
         
     | 
| 
      
 18 
     | 
    
         
            +
                autoload :Ref, 'jsi/schema/ref'
         
     | 
| 
       12 
19 
     | 
    
         | 
| 
       13 
20 
     | 
    
         
             
                autoload :SchemaAncestorNode, 'jsi/schema/schema_ancestor_node'
         
     | 
| 
       14 
21 
     | 
    
         | 
| 
       15 
     | 
    
         
            -
                autoload :Ref, 'jsi/schema/ref'
         
     | 
| 
       16 
     | 
    
         
            -
             
     | 
| 
       17 
22 
     | 
    
         
             
                autoload :Draft04, 'jsi/schema/draft04'
         
     | 
| 
       18 
23 
     | 
    
         
             
                autoload :Draft06, 'jsi/schema/draft06'
         
     | 
| 
       19 
24 
     | 
    
         
             
                autoload :Draft07, 'jsi/schema/draft07'
         
     | 
| 
         @@ -34,7 +39,7 @@ module JSI 
     | 
|
| 
       34 
39 
     | 
    
         
             
                  # the contents of a $id keyword whose value is a string, or nil
         
     | 
| 
       35 
40 
     | 
    
         
             
                  # @return [#to_str, nil]
         
     | 
| 
       36 
41 
     | 
    
         
             
                  def id
         
     | 
| 
       37 
     | 
    
         
            -
                    if  
     | 
| 
      
 42 
     | 
    
         
            +
                    if keyword?('$id') && schema_content['$id'].respond_to?(:to_str)
         
     | 
| 
       38 
43 
     | 
    
         
             
                      schema_content['$id']
         
     | 
| 
       39 
44 
     | 
    
         
             
                    else
         
     | 
| 
       40 
45 
     | 
    
         
             
                      nil
         
     | 
| 
         @@ -47,7 +52,7 @@ module JSI 
     | 
|
| 
       47 
52 
     | 
    
         
             
                  # the contents of an `id` keyword whose value is a string, or nil
         
     | 
| 
       48 
53 
     | 
    
         
             
                  # @return [#to_str, nil]
         
     | 
| 
       49 
54 
     | 
    
         
             
                  def id
         
     | 
| 
       50 
     | 
    
         
            -
                    if  
     | 
| 
      
 55 
     | 
    
         
            +
                    if keyword?('id') && schema_content['id'].respond_to?(:to_str)
         
     | 
| 
       51 
56 
     | 
    
         
             
                      schema_content['id']
         
     | 
| 
       52 
57 
     | 
    
         
             
                    else
         
     | 
| 
       53 
58 
     | 
    
         
             
                      nil
         
     | 
| 
         @@ -62,7 +67,7 @@ module JSI 
     | 
|
| 
       62 
67 
     | 
    
         
             
                  # @return [Addressable::URI, nil]
         
     | 
| 
       63 
68 
     | 
    
         
             
                  def id_without_fragment
         
     | 
| 
       64 
69 
     | 
    
         
             
                    if id
         
     | 
| 
       65 
     | 
    
         
            -
                      id_uri =  
     | 
| 
      
 70 
     | 
    
         
            +
                      id_uri = Util.uri(id)
         
     | 
| 
       66 
71 
     | 
    
         
             
                      if id_uri.merge(fragment: nil).empty?
         
     | 
| 
       67 
72 
     | 
    
         
             
                        # fragment-only id is just an anchor
         
     | 
| 
       68 
73 
     | 
    
         
             
                        # e.g. #foo
         
     | 
| 
         @@ -74,7 +79,7 @@ module JSI 
     | 
|
| 
       74 
79 
     | 
    
         
             
                      elsif id_uri.fragment == ''
         
     | 
| 
       75 
80 
     | 
    
         
             
                        # empty fragment
         
     | 
| 
       76 
81 
     | 
    
         
             
                        # e.g. http://json-schema.org/draft-07/schema#
         
     | 
| 
       77 
     | 
    
         
            -
                        id_uri.merge(fragment: nil)
         
     | 
| 
      
 82 
     | 
    
         
            +
                        id_uri.merge(fragment: nil).freeze
         
     | 
| 
       78 
83 
     | 
    
         
             
                      elsif jsi_schema_base_uri && jsi_schema_base_uri.join(id_uri).merge(fragment: nil) == jsi_schema_base_uri
         
     | 
| 
       79 
84 
     | 
    
         
             
                        # the id, resolved against the base uri, consists of the base uri plus an anchor fragment.
         
     | 
| 
       80 
85 
     | 
    
         
             
                        # so there's no non-fragment id.
         
     | 
| 
         @@ -83,7 +88,7 @@ module JSI 
     | 
|
| 
       83 
88 
     | 
    
         
             
                        nil
         
     | 
| 
       84 
89 
     | 
    
         
             
                      else
         
     | 
| 
       85 
90 
     | 
    
         
             
                        # e.g. http://localhost:1234/bar#foo
         
     | 
| 
       86 
     | 
    
         
            -
                        id_uri.merge(fragment: nil)
         
     | 
| 
      
 91 
     | 
    
         
            +
                        id_uri.merge(fragment: nil).freeze
         
     | 
| 
       87 
92 
     | 
    
         
             
                      end
         
     | 
| 
       88 
93 
     | 
    
         
             
                    else
         
     | 
| 
       89 
94 
     | 
    
         
             
                      nil
         
     | 
| 
         @@ -94,7 +99,7 @@ module JSI 
     | 
|
| 
       94 
99 
     | 
    
         
             
                  # @return [String]
         
     | 
| 
       95 
100 
     | 
    
         
             
                  def anchor
         
     | 
| 
       96 
101 
     | 
    
         
             
                    if id
         
     | 
| 
       97 
     | 
    
         
            -
                      id_uri =  
     | 
| 
      
 102 
     | 
    
         
            +
                      id_uri = Util.uri(id)
         
     | 
| 
       98 
103 
     | 
    
         
             
                      if id_uri.fragment == ''
         
     | 
| 
       99 
104 
     | 
    
         
             
                        nil
         
     | 
| 
       100 
105 
     | 
    
         
             
                      else
         
     | 
| 
         @@ -128,141 +133,235 @@ module JSI 
     | 
|
| 
       128 
133 
     | 
    
         
             
                  end
         
     | 
| 
       129 
134 
     | 
    
         
             
                end
         
     | 
| 
       130 
135 
     | 
    
         | 
| 
       131 
     | 
    
         
            -
                # JSI 
     | 
| 
       132 
     | 
    
         
            -
                # extends a JSI::Schema instance and indicates that JSIs which instantiate the schema
         
     | 
| 
       133 
     | 
    
         
            -
                # are themselves also schemas.
         
     | 
| 
      
 136 
     | 
    
         
            +
                # This module extends any JSI Schema that is a meta-schema, i.e. it describes schemas.
         
     | 
| 
       134 
137 
     | 
    
         
             
                #
         
     | 
| 
       135 
     | 
    
         
            -
                #  
     | 
| 
      
 138 
     | 
    
         
            +
                # Examples of a meta-schema include the JSON Schema meta-schemas and
         
     | 
| 
       136 
139 
     | 
    
         
             
                # the OpenAPI schema definition which describes "A deterministic version of a JSON Schema object."
         
     | 
| 
       137 
     | 
    
         
            -
                 
     | 
| 
       138 
     | 
    
         
            -
             
     | 
| 
      
 140 
     | 
    
         
            +
                #
         
     | 
| 
      
 141 
     | 
    
         
            +
                # Meta-schemas include {JSI::Schema} in their
         
     | 
| 
      
 142 
     | 
    
         
            +
                # {Schema#jsi_schema_module JSI Schema module}, so for a schema which is an instance of
         
     | 
| 
      
 143 
     | 
    
         
            +
                # JSI::Schema::MetaSchema, instances of that schema are instances of {JSI::Schema} and are schemas.
         
     | 
| 
      
 144 
     | 
    
         
            +
                #
         
     | 
| 
      
 145 
     | 
    
         
            +
                # A schema is indicated as describing other schemas using the {Schema#describes_schema!} method.
         
     | 
| 
      
 146 
     | 
    
         
            +
                module MetaSchema
         
     | 
| 
      
 147 
     | 
    
         
            +
                  # @return [Set<Module>]
         
     | 
| 
      
 148 
     | 
    
         
            +
                  attr_reader(:schema_implementation_modules)
         
     | 
| 
      
 149 
     | 
    
         
            +
             
     | 
| 
      
 150 
     | 
    
         
            +
                  # Instantiates the given schema content as a JSI Schema.
         
     | 
| 
      
 151 
     | 
    
         
            +
                  #
         
     | 
| 
      
 152 
     | 
    
         
            +
                  # By default, the schema will be registered with the {JSI.schema_registry}.
         
     | 
| 
      
 153 
     | 
    
         
            +
                  # This can be controlled by params `register` and `schema_registry`.
         
     | 
| 
       139 
154 
     | 
    
         
             
                  #
         
     | 
| 
       140 
     | 
    
         
            -
                  #  
     | 
| 
       141 
     | 
    
         
            -
                  #  
     | 
| 
       142 
     | 
    
         
            -
                  # given instance.
         
     | 
| 
      
 155 
     | 
    
         
            +
                  # By default, the `schema_content` will have any Symbol keys of Hashes replaced with Strings
         
     | 
| 
      
 156 
     | 
    
         
            +
                  # (recursively through the document). This is controlled by the param `stringify_symbol_keys`.
         
     | 
| 
       143 
157 
     | 
    
         
             
                  #
         
     | 
| 
       144 
     | 
    
         
            -
                  #  
     | 
| 
      
 158 
     | 
    
         
            +
                  # @param schema_content an object to be instantiated as a JSI Schema - typically a Hash
         
     | 
| 
      
 159 
     | 
    
         
            +
                  # @param uri [#to_str, Addressable::URI] The retrieval URI of the schema document.
         
     | 
| 
      
 160 
     | 
    
         
            +
                  #   If specified, the root schema will be identified by this URI, in addition
         
     | 
| 
      
 161 
     | 
    
         
            +
                  #   to any absolute URI declared with an id keyword, for resolution in the `schema_registry`.
         
     | 
| 
       145 
162 
     | 
    
         
             
                  #
         
     | 
| 
       146 
     | 
    
         
            -
                  #  
     | 
| 
       147 
     | 
    
         
            -
                  #  
     | 
| 
       148 
     | 
    
         
            -
                  #    
     | 
| 
       149 
     | 
    
         
            -
                  # 
     | 
| 
       150 
     | 
    
         
            -
                  #  
     | 
| 
       151 
     | 
    
         
            -
                  # 
     | 
| 
      
 163 
     | 
    
         
            +
                  #   It is rare that this needs to be specified. Most schemas, if they use absolute URIs, will
         
     | 
| 
      
 164 
     | 
    
         
            +
                  #   use the `$id` keyword (`id` in draft 4) to specify this. A different retrieval URI is useful
         
     | 
| 
      
 165 
     | 
    
         
            +
                  #   in unusual cases:
         
     | 
| 
      
 166 
     | 
    
         
            +
                  #
         
     | 
| 
      
 167 
     | 
    
         
            +
                  #     - A schema in the document uses relative URIs for `$id` or `$ref` without an absolute id in an
         
     | 
| 
      
 168 
     | 
    
         
            +
                  #       ancestor schema - these will be resolved relative to this URI
         
     | 
| 
      
 169 
     | 
    
         
            +
                  #     - Another schema refers with `$ref` to the schema being instantiated by this retrieval URI,
         
     | 
| 
      
 170 
     | 
    
         
            +
                  #       rather than an id declared in the schema - the schema is resolvable by this URI in the
         
     | 
| 
      
 171 
     | 
    
         
            +
                  #       `schema_registry`.
         
     | 
| 
      
 172 
     | 
    
         
            +
                  # @param register [Boolean] Whether the instantiated schema and any subschemas with absolute URIs
         
     | 
| 
      
 173 
     | 
    
         
            +
                  #   will be registered in the schema registry indicated by param `schema_registry`.
         
     | 
| 
      
 174 
     | 
    
         
            +
                  # @param schema_registry [SchemaRegistry, nil] The registry this schema will use.
         
     | 
| 
      
 175 
     | 
    
         
            +
                  #
         
     | 
| 
      
 176 
     | 
    
         
            +
                  #   - The schema and subschemas will be registered here with any declared URI,
         
     | 
| 
      
 177 
     | 
    
         
            +
                  #     unless the `register` param is false.
         
     | 
| 
      
 178 
     | 
    
         
            +
                  #   - References from within the schema (typically from `$ref` keywords) are resolved using this registry.
         
     | 
| 
      
 179 
     | 
    
         
            +
                  # @param stringify_symbol_keys [Boolean] Whether the schema content will have any Symbol keys of Hashes
         
     | 
| 
      
 180 
     | 
    
         
            +
                  #   replaced with Strings (recursively through the document).
         
     | 
| 
      
 181 
     | 
    
         
            +
                  #   Replacement is done on a copy; the given schema content is not modified.
         
     | 
| 
      
 182 
     | 
    
         
            +
                  # @param to_immutable (see SchemaSet#new_jsi)
         
     | 
| 
      
 183 
     | 
    
         
            +
                  # @yield If a block is given, it is evaluated in the context of the schema's JSI schema module
         
     | 
| 
      
 184 
     | 
    
         
            +
                  #   using [Module#module_exec](https://ruby-doc.org/core/Module.html#method-i-module_exec).
         
     | 
| 
      
 185 
     | 
    
         
            +
                  # @return [JSI::Base subclass + JSI::Schema] a JSI which is a {JSI::Schema} whose content comes from
         
     | 
| 
      
 186 
     | 
    
         
            +
                  #   the given `schema_content` and whose schemas are this schema's inplace applicators.
         
     | 
| 
       152 
187 
     | 
    
         
             
                  def new_schema(schema_content,
         
     | 
| 
       153 
     | 
    
         
            -
                      uri: nil
         
     | 
| 
      
 188 
     | 
    
         
            +
                      uri: nil,
         
     | 
| 
      
 189 
     | 
    
         
            +
                      register: true,
         
     | 
| 
      
 190 
     | 
    
         
            +
                      schema_registry: JSI.schema_registry,
         
     | 
| 
      
 191 
     | 
    
         
            +
                      stringify_symbol_keys: true,
         
     | 
| 
      
 192 
     | 
    
         
            +
                      to_immutable: DEFAULT_CONTENT_TO_IMMUTABLE,
         
     | 
| 
      
 193 
     | 
    
         
            +
                      &block
         
     | 
| 
       154 
194 
     | 
    
         
             
                  )
         
     | 
| 
       155 
     | 
    
         
            -
                    schema_jsi = new_jsi( 
     | 
| 
      
 195 
     | 
    
         
            +
                    schema_jsi = new_jsi(schema_content,
         
     | 
| 
       156 
196 
     | 
    
         
             
                      uri: uri,
         
     | 
| 
      
 197 
     | 
    
         
            +
                      register: register,
         
     | 
| 
      
 198 
     | 
    
         
            +
                      schema_registry: schema_registry,
         
     | 
| 
      
 199 
     | 
    
         
            +
                      stringify_symbol_keys: stringify_symbol_keys,
         
     | 
| 
      
 200 
     | 
    
         
            +
                      to_immutable: to_immutable,
         
     | 
| 
       157 
201 
     | 
    
         
             
                    )
         
     | 
| 
       158 
     | 
    
         
            -
             
     | 
| 
      
 202 
     | 
    
         
            +
             
     | 
| 
      
 203 
     | 
    
         
            +
                    schema_jsi.jsi_schema_module_exec(&block) if block
         
     | 
| 
      
 204 
     | 
    
         
            +
             
     | 
| 
       159 
205 
     | 
    
         
             
                    schema_jsi
         
     | 
| 
       160 
206 
     | 
    
         
             
                  end
         
     | 
| 
       161 
207 
     | 
    
         | 
| 
       162 
     | 
    
         
            -
                  #  
     | 
| 
      
 208 
     | 
    
         
            +
                  # Instantiates the given schema content as a JSI Schema, passing all params to
         
     | 
| 
      
 209 
     | 
    
         
            +
                  # {Schema::MetaSchema#new_schema}, and returns its {Schema#jsi_schema_module JSI Schema Module}.
         
     | 
| 
       163 
210 
     | 
    
         
             
                  #
         
     | 
| 
       164 
     | 
    
         
            -
                  #  
     | 
| 
       165 
     | 
    
         
            -
                   
     | 
| 
       166 
     | 
    
         
            -
             
     | 
| 
       167 
     | 
    
         
            -
                  # @return [Module, JSI::SchemaModule] the JSI Schema Module of the schema
         
     | 
| 
       168 
     | 
    
         
            -
                  def new_schema_module(schema_content, **kw)
         
     | 
| 
       169 
     | 
    
         
            -
                    new_schema(schema_content, **kw).jsi_schema_module
         
     | 
| 
      
 211 
     | 
    
         
            +
                  # @return [JSI::SchemaModule] the JSI Schema Module of the instantiated schema
         
     | 
| 
      
 212 
     | 
    
         
            +
                  def new_schema_module(schema_content, **kw, &block)
         
     | 
| 
      
 213 
     | 
    
         
            +
                    new_schema(schema_content, **kw, &block).jsi_schema_module
         
     | 
| 
       170 
214 
     | 
    
         
             
                  end
         
     | 
| 
       171 
215 
     | 
    
         
             
                end
         
     | 
| 
       172 
216 
     | 
    
         | 
| 
       173 
217 
     | 
    
         
             
                class << self
         
     | 
| 
       174 
     | 
    
         
            -
                   
     | 
| 
      
 218 
     | 
    
         
            +
                  def extended(o)
         
     | 
| 
      
 219 
     | 
    
         
            +
                    super
         
     | 
| 
      
 220 
     | 
    
         
            +
                    o.send(:jsi_schema_initialize)
         
     | 
| 
      
 221 
     | 
    
         
            +
                  end
         
     | 
| 
      
 222 
     | 
    
         
            +
                end
         
     | 
| 
      
 223 
     | 
    
         
            +
              end
         
     | 
| 
      
 224 
     | 
    
         
            +
             
     | 
| 
      
 225 
     | 
    
         
            +
              class << self
         
     | 
| 
      
 226 
     | 
    
         
            +
                  # An application-wide default meta-schema set by {default_metaschema=}, used by {JSI.new_schema}
         
     | 
| 
      
 227 
     | 
    
         
            +
                  # to instantiate schemas that do not specify their meta-schema using a `$schema` property.
         
     | 
| 
       175 
228 
     | 
    
         
             
                  #
         
     | 
| 
       176 
     | 
    
         
            -
                  # @return [nil,  
     | 
| 
      
 229 
     | 
    
         
            +
                  # @return [nil, Base + Schema + Schema::MetaSchema]
         
     | 
| 
       177 
230 
     | 
    
         
             
                  def default_metaschema
         
     | 
| 
       178 
     | 
    
         
            -
                     
     | 
| 
       179 
     | 
    
         
            -
                    return JSONSchemaOrgDraft07
         
     | 
| 
      
 231 
     | 
    
         
            +
                    @default_metaschema
         
     | 
| 
       180 
232 
     | 
    
         
             
                  end
         
     | 
| 
       181 
233 
     | 
    
         | 
| 
       182 
     | 
    
         
            -
                  #  
     | 
| 
      
 234 
     | 
    
         
            +
                  # Sets {default_metaschema} to a schema indicated by the given param.
         
     | 
| 
      
 235 
     | 
    
         
            +
                  #
         
     | 
| 
      
 236 
     | 
    
         
            +
                  # @param default_metaschema [Schema::MetaSchema, SchemaModule::MetaSchemaModule, #to_str, nil]
         
     | 
| 
      
 237 
     | 
    
         
            +
                  #   Indicates the default meta-schema.
         
     | 
| 
      
 238 
     | 
    
         
            +
                  #   This may be a meta-schema or a meta-schema's schema module (e.g. `JSI::JSONSchemaDraft07`),
         
     | 
| 
      
 239 
     | 
    
         
            +
                  #   or a URI (as would be in a `$schema` keyword).
         
     | 
| 
       183 
240 
     | 
    
         
             
                  #
         
     | 
| 
       184 
     | 
    
         
            -
                  #  
     | 
| 
       185 
     | 
    
         
            -
                  #   metaschema's schema module (e.g. `JSI::JSONSchemaOrgDraft07`).
         
     | 
| 
      
 241 
     | 
    
         
            +
                  #   `nil` to unset.
         
     | 
| 
       186 
242 
     | 
    
         
             
                  def default_metaschema=(default_metaschema)
         
     | 
| 
       187 
     | 
    
         
            -
                     
     | 
| 
       188 
     | 
    
         
            -
                      raise(TypeError, "given default_metaschema does not respond to #new_schema")
         
     | 
| 
       189 
     | 
    
         
            -
                    end
         
     | 
| 
       190 
     | 
    
         
            -
                    @default_metaschema = default_metaschema
         
     | 
| 
      
 243 
     | 
    
         
            +
                    @default_metaschema = default_metaschema.nil? ? nil : ensure_metaschema(default_metaschema)
         
     | 
| 
       191 
244 
     | 
    
         
             
                  end
         
     | 
| 
       192 
245 
     | 
    
         | 
| 
       193 
     | 
    
         
            -
                  #  
     | 
| 
      
 246 
     | 
    
         
            +
                  # Instantiates the given schema content as a JSI Schema.
         
     | 
| 
      
 247 
     | 
    
         
            +
                  #
         
     | 
| 
      
 248 
     | 
    
         
            +
                  # The meta-schema that describes the schema must be indicated:
         
     | 
| 
       194 
249 
     | 
    
         
             
                  #
         
     | 
| 
       195 
     | 
    
         
            -
                  #  
     | 
| 
      
 250 
     | 
    
         
            +
                  # - If the schema object has a `$schema` property, that URI is resolved using the `schema_registry`
         
     | 
| 
      
 251 
     | 
    
         
            +
                  #   param (by default {JSI.schema_registry}), and that meta-schema is used. For example:
         
     | 
| 
      
 252 
     | 
    
         
            +
                  #
         
     | 
| 
      
 253 
     | 
    
         
            +
                  #   ```ruby
         
     | 
| 
      
 254 
     | 
    
         
            +
                  #   JSI.new_schema({
         
     | 
| 
      
 255 
     | 
    
         
            +
                  #     "$schema" => "http://json-schema.org/draft-07/schema#",
         
     | 
| 
      
 256 
     | 
    
         
            +
                  #     "properties" => ...,
         
     | 
| 
      
 257 
     | 
    
         
            +
                  #   })
         
     | 
| 
      
 258 
     | 
    
         
            +
                  #   ```
         
     | 
| 
       196 
259 
     | 
    
         
             
                  #
         
     | 
| 
       197 
     | 
    
         
            -
                  # - if the schema object has a `$schema` property, that URI is resolved using the {JSI.schema_registry},
         
     | 
| 
       198 
     | 
    
         
            -
                  #   and that metaschema is used.
         
     | 
| 
       199 
260 
     | 
    
         
             
                  # - if no `$schema` property is present, the `default_metaschema` param is used, if the caller
         
     | 
| 
       200 
     | 
    
         
            -
                  #   specifies it.
         
     | 
| 
      
 261 
     | 
    
         
            +
                  #   specifies it. For example:
         
     | 
| 
      
 262 
     | 
    
         
            +
                  #
         
     | 
| 
      
 263 
     | 
    
         
            +
                  #   ```ruby
         
     | 
| 
      
 264 
     | 
    
         
            +
                  #   JSI.new_schema({"properties" => ...}, default_metaschema: JSI::JSONSchemaDraft07)
         
     | 
| 
      
 265 
     | 
    
         
            +
                  #   ```
         
     | 
| 
      
 266 
     | 
    
         
            +
                  #
         
     | 
| 
       201 
267 
     | 
    
         
             
                  # - if no `default_metaschema` param is specified, the application-wide default
         
     | 
| 
       202 
     | 
    
         
            -
                  #   {JSI 
     | 
| 
       203 
     | 
    
         
            -
                  #   if the application has set it.
         
     | 
| 
      
 268 
     | 
    
         
            +
                  #   {JSI.default_metaschema JSI.default_metaschema} is used,
         
     | 
| 
      
 269 
     | 
    
         
            +
                  #   if the application has set it. For example:
         
     | 
| 
       204 
270 
     | 
    
         
             
                  #
         
     | 
| 
       205 
     | 
    
         
            -
                  # 
     | 
| 
      
 271 
     | 
    
         
            +
                  #   ```ruby
         
     | 
| 
      
 272 
     | 
    
         
            +
                  #   JSI.default_metaschema = JSI::JSONSchemaDraft07
         
     | 
| 
      
 273 
     | 
    
         
            +
                  #   JSI.new_schema({"properties" => ...})
         
     | 
| 
      
 274 
     | 
    
         
            +
                  #   ```
         
     | 
| 
       206 
275 
     | 
    
         
             
                  #
         
     | 
| 
       207 
     | 
    
         
            -
                  #  
     | 
| 
       208 
     | 
    
         
            -
                  # passing the `default_metaschema` param is to use `.new_schema` on the metaschema or its module, e.g.
         
     | 
| 
       209 
     | 
    
         
            -
                  # `JSI::JSONSchemaOrgDraft07.new_schema(my_schema_object)`
         
     | 
| 
      
 276 
     | 
    
         
            +
                  # An ArgumentError is raised if none of these indicates a meta-schema to use.
         
     | 
| 
       210 
277 
     | 
    
         
             
                  #
         
     | 
| 
       211 
     | 
    
         
            -
                  # if  
     | 
| 
       212 
     | 
    
         
            -
                  #  
     | 
| 
       213 
     | 
    
         
            -
                  # Schema# 
     | 
| 
      
 278 
     | 
    
         
            +
                  # Note that if you are instantiating a schema known to have no `$schema` property, an alternative to
         
     | 
| 
      
 279 
     | 
    
         
            +
                  # specifying a `default_metaschema` is to call `new_schema` on the
         
     | 
| 
      
 280 
     | 
    
         
            +
                  # {Schema::MetaSchema#new_schema meta-schema} or its
         
     | 
| 
      
 281 
     | 
    
         
            +
                  # {SchemaModule::MetaSchemaModule#new_schema schema module}, e.g.
         
     | 
| 
      
 282 
     | 
    
         
            +
                  # `JSI::JSONSchemaDraft07.new_schema(my_schema_content)`
         
     | 
| 
       214 
283 
     | 
    
         
             
                  #
         
     | 
| 
       215 
     | 
    
         
            -
                  # @param  
     | 
| 
       216 
     | 
    
         
            -
                  # 
     | 
| 
       217 
     | 
    
         
            -
                  #  
     | 
| 
       218 
     | 
    
         
            -
                  #  
     | 
| 
       219 
     | 
    
         
            -
                  #   a  
     | 
| 
       220 
     | 
    
         
            -
                  # 
     | 
| 
       221 
     | 
    
         
            -
                  # @ 
     | 
| 
       222 
     | 
    
         
            -
                   
     | 
| 
      
 284 
     | 
    
         
            +
                  # @param schema_content (see Schema::MetaSchema#new_schema)
         
     | 
| 
      
 285 
     | 
    
         
            +
                  # @param default_metaschema [Schema::MetaSchema, SchemaModule::MetaSchemaModule, #to_str]
         
     | 
| 
      
 286 
     | 
    
         
            +
                  #   Indicates the meta-schema to use if the given `schema_content` does not have a `$schema` property.
         
     | 
| 
      
 287 
     | 
    
         
            +
                  #   This may be a meta-schema or a meta-schema's schema module (e.g. `JSI::JSONSchemaDraft07`),
         
     | 
| 
      
 288 
     | 
    
         
            +
                  #   or a URI (as would be in a `$schema` keyword).
         
     | 
| 
      
 289 
     | 
    
         
            +
                  # @param uri (see Schema::MetaSchema#new_schema)
         
     | 
| 
      
 290 
     | 
    
         
            +
                  # @param register (see Schema::MetaSchema#new_schema)
         
     | 
| 
      
 291 
     | 
    
         
            +
                  # @param schema_registry (see Schema::MetaSchema#new_schema)
         
     | 
| 
      
 292 
     | 
    
         
            +
                  # @param stringify_symbol_keys (see Schema::MetaSchema#new_schema)
         
     | 
| 
      
 293 
     | 
    
         
            +
                  # @param to_immutable (see Schema::DescribesSchema#new_schema)
         
     | 
| 
      
 294 
     | 
    
         
            +
                  # @yield (see Schema::MetaSchema#new_schema)
         
     | 
| 
      
 295 
     | 
    
         
            +
                  # @return [JSI::Base subclass + JSI::Schema] a JSI which is a {JSI::Schema} whose content comes from
         
     | 
| 
      
 296 
     | 
    
         
            +
                  #   the given `schema_content` and whose schemas are inplace applicators of the indicated meta-schema
         
     | 
| 
      
 297 
     | 
    
         
            +
                  def new_schema(schema_content,
         
     | 
| 
      
 298 
     | 
    
         
            +
                      default_metaschema: nil,
         
     | 
| 
      
 299 
     | 
    
         
            +
                      # params of Schema::MetaSchema#new_schema have their default values repeated here. delegating in a splat
         
     | 
| 
      
 300 
     | 
    
         
            +
                      # would remove repetition, but yard doesn't display delegated defaults with its (see X) directive.
         
     | 
| 
      
 301 
     | 
    
         
            +
                      uri: nil,
         
     | 
| 
      
 302 
     | 
    
         
            +
                      register: true,
         
     | 
| 
      
 303 
     | 
    
         
            +
                      schema_registry: JSI.schema_registry,
         
     | 
| 
      
 304 
     | 
    
         
            +
                      stringify_symbol_keys: true,
         
     | 
| 
      
 305 
     | 
    
         
            +
                      to_immutable: DEFAULT_CONTENT_TO_IMMUTABLE,
         
     | 
| 
      
 306 
     | 
    
         
            +
                      &block
         
     | 
| 
      
 307 
     | 
    
         
            +
                  )
         
     | 
| 
      
 308 
     | 
    
         
            +
                    new_schema_params = {
         
     | 
| 
      
 309 
     | 
    
         
            +
                      uri: uri,
         
     | 
| 
      
 310 
     | 
    
         
            +
                      register: register,
         
     | 
| 
      
 311 
     | 
    
         
            +
                      schema_registry: schema_registry,
         
     | 
| 
      
 312 
     | 
    
         
            +
                      stringify_symbol_keys: stringify_symbol_keys,
         
     | 
| 
      
 313 
     | 
    
         
            +
                      to_immutable: to_immutable,
         
     | 
| 
      
 314 
     | 
    
         
            +
                    }
         
     | 
| 
       223 
315 
     | 
    
         
             
                    default_metaschema_new_schema = -> {
         
     | 
| 
       224 
     | 
    
         
            -
                      default_metaschema  
     | 
| 
       225 
     | 
    
         
            -
             
     | 
| 
      
 316 
     | 
    
         
            +
                      default_metaschema = if default_metaschema
         
     | 
| 
      
 317 
     | 
    
         
            +
                        Schema.ensure_metaschema(default_metaschema, name: "default_metaschema")
         
     | 
| 
      
 318 
     | 
    
         
            +
                      elsif self.default_metaschema
         
     | 
| 
      
 319 
     | 
    
         
            +
                        self.default_metaschema
         
     | 
| 
      
 320 
     | 
    
         
            +
                      else
         
     | 
| 
       226 
321 
     | 
    
         
             
                        raise(ArgumentError, [
         
     | 
| 
       227 
     | 
    
         
            -
                          " 
     | 
| 
       228 
     | 
    
         
            -
                          " 
     | 
| 
       229 
     | 
    
         
            -
                          "JSI 
     | 
| 
       230 
     | 
    
         
            -
                          " 
     | 
| 
       231 
     | 
    
         
            -
                          " 
     | 
| 
      
 322 
     | 
    
         
            +
                          "When instantiating a schema with no `$schema` property, you must specify its meta-schema by one of these methods:",
         
     | 
| 
      
 323 
     | 
    
         
            +
                          "- pass the `default_metaschema` param to this method",
         
     | 
| 
      
 324 
     | 
    
         
            +
                          "  e.g.: JSI.new_schema(..., default_metaschema: JSI::JSONSchemaDraft07)",
         
     | 
| 
      
 325 
     | 
    
         
            +
                          "- invoke `new_schema` on the appropriate meta-schema or its schema module",
         
     | 
| 
      
 326 
     | 
    
         
            +
                          "  e.g.: JSI::JSONSchemaDraft07.new_schema(...)",
         
     | 
| 
      
 327 
     | 
    
         
            +
                          "- set JSI.default_metaschema to an application-wide default meta-schema initially",
         
     | 
| 
      
 328 
     | 
    
         
            +
                          "  e.g.: JSI.default_metaschema = JSI::JSONSchemaDraft07",
         
     | 
| 
      
 329 
     | 
    
         
            +
                          "instantiating schema_content: #{schema_content.pretty_inspect.chomp}",
         
     | 
| 
       232 
330 
     | 
    
         
             
                        ].join("\n"))
         
     | 
| 
       233 
331 
     | 
    
         
             
                      end
         
     | 
| 
       234 
     | 
    
         
            -
                       
     | 
| 
       235 
     | 
    
         
            -
                        raise(TypeError, "given default_metaschema does not respond to #new_schema: #{default_metaschema.pretty_inspect.chomp}")
         
     | 
| 
       236 
     | 
    
         
            -
                      end
         
     | 
| 
       237 
     | 
    
         
            -
                      default_metaschema.new_schema(schema_object, **kw)
         
     | 
| 
      
 332 
     | 
    
         
            +
                      default_metaschema.new_schema(schema_content, **new_schema_params, &block)
         
     | 
| 
       238 
333 
     | 
    
         
             
                    }
         
     | 
| 
       239 
     | 
    
         
            -
                    if  
     | 
| 
       240 
     | 
    
         
            -
                       
     | 
| 
       241 
     | 
    
         
            -
             
     | 
| 
       242 
     | 
    
         
            -
             
     | 
| 
       243 
     | 
    
         
            -
             
     | 
| 
       244 
     | 
    
         
            -
             
     | 
| 
       245 
     | 
    
         
            -
             
     | 
| 
       246 
     | 
    
         
            -
                         
     | 
| 
       247 
     | 
    
         
            -
             
     | 
| 
      
 334 
     | 
    
         
            +
                    if schema_content.is_a?(Schema)
         
     | 
| 
      
 335 
     | 
    
         
            +
                      raise(TypeError, [
         
     | 
| 
      
 336 
     | 
    
         
            +
                        "Given schema_content is already a JSI::Schema. It cannot be instantiated as the content of a schema.",
         
     | 
| 
      
 337 
     | 
    
         
            +
                        "given: #{schema_content.pretty_inspect.chomp}",
         
     | 
| 
      
 338 
     | 
    
         
            +
                      ].join("\n"))
         
     | 
| 
      
 339 
     | 
    
         
            +
                    elsif schema_content.is_a?(JSI::Base)
         
     | 
| 
      
 340 
     | 
    
         
            +
                      raise(TypeError, [
         
     | 
| 
      
 341 
     | 
    
         
            +
                        "Given schema_content is a JSI::Base. It cannot be instantiated as the content of a schema.",
         
     | 
| 
      
 342 
     | 
    
         
            +
                        "given: #{schema_content.pretty_inspect.chomp}",
         
     | 
| 
      
 343 
     | 
    
         
            +
                      ].join("\n"))
         
     | 
| 
      
 344 
     | 
    
         
            +
                    elsif schema_content.respond_to?(:to_hash)
         
     | 
| 
      
 345 
     | 
    
         
            +
                      id = schema_content['$schema'] || stringify_symbol_keys && schema_content[:'$schema']
         
     | 
| 
      
 346 
     | 
    
         
            +
                      if id
         
     | 
| 
      
 347 
     | 
    
         
            +
                        unless id.respond_to?(:to_str)
         
     | 
| 
      
 348 
     | 
    
         
            +
                          raise(ArgumentError, "given schema_content keyword `$schema` is not a string")
         
     | 
| 
       248 
349 
     | 
    
         
             
                        end
         
     | 
| 
       249 
     | 
    
         
            -
                        metaschema. 
     | 
| 
      
 350 
     | 
    
         
            +
                        metaschema = Schema.ensure_metaschema(id, name: '$schema', schema_registry: schema_registry)
         
     | 
| 
      
 351 
     | 
    
         
            +
                        metaschema.new_schema(schema_content, **new_schema_params, &block)
         
     | 
| 
       250 
352 
     | 
    
         
             
                      else
         
     | 
| 
       251 
353 
     | 
    
         
             
                        default_metaschema_new_schema.call
         
     | 
| 
       252 
354 
     | 
    
         
             
                      end
         
     | 
| 
       253 
     | 
    
         
            -
                    elsif [true, false].include?(schema_object)
         
     | 
| 
       254 
     | 
    
         
            -
                      default_metaschema_new_schema.call
         
     | 
| 
       255 
355 
     | 
    
         
             
                    else
         
     | 
| 
       256 
     | 
    
         
            -
                       
     | 
| 
      
 356 
     | 
    
         
            +
                      default_metaschema_new_schema.call
         
     | 
| 
       257 
357 
     | 
    
         
             
                    end
         
     | 
| 
       258 
358 
     | 
    
         
             
                  end
         
     | 
| 
      
 359 
     | 
    
         
            +
              end
         
     | 
| 
       259 
360 
     | 
    
         | 
| 
       260 
     | 
    
         
            -
             
     | 
| 
       261 
     | 
    
         
            -
                  alias_method :new, :new_schema
         
     | 
| 
       262 
     | 
    
         
            -
             
     | 
| 
       263 
     | 
    
         
            -
                  # @deprecated
         
     | 
| 
       264 
     | 
    
         
            -
                  alias_method :from_object, :new_schema
         
     | 
| 
      
 361 
     | 
    
         
            +
              self.default_metaschema = nil
         
     | 
| 
       265 
362 
     | 
    
         | 
| 
      
 363 
     | 
    
         
            +
              module Schema
         
     | 
| 
      
 364 
     | 
    
         
            +
                class << self
         
     | 
| 
       266 
365 
     | 
    
         
             
                  # ensure the given object is a JSI Schema
         
     | 
| 
       267 
366 
     | 
    
         
             
                  #
         
     | 
| 
       268 
367 
     | 
    
         
             
                  # @param schema [Object] the thing the caller wishes to ensure is a Schema
         
     | 
| 
         @@ -274,19 +373,25 @@ module JSI 
     | 
|
| 
       274 
373 
     | 
    
         
             
                    if schema.is_a?(Schema)
         
     | 
| 
       275 
374 
     | 
    
         
             
                      schema
         
     | 
| 
       276 
375 
     | 
    
         
             
                    else
         
     | 
| 
       277 
     | 
    
         
            -
                      if reinstantiate_as
         
     | 
| 
      
 376 
     | 
    
         
            +
                      if reinstantiate_as && schema.is_a?(JSI::Base)
         
     | 
| 
       278 
377 
     | 
    
         
             
                        # TODO warn; behavior is undefined and I hate this implementation
         
     | 
| 
       279 
378 
     | 
    
         | 
| 
       280 
     | 
    
         
            -
                         
     | 
| 
      
 379 
     | 
    
         
            +
                        result_schema_indicated_schemas = SchemaSet.new(schema.jsi_indicated_schemas + reinstantiate_as)
         
     | 
| 
      
 380 
     | 
    
         
            +
                        result_schema_applied_schemas = result_schema_indicated_schemas.inplace_applicator_schemas(schema.jsi_node_content)
         
     | 
| 
       281 
381 
     | 
    
         | 
| 
       282 
     | 
    
         
            -
                        result_schema_class = JSI::SchemaClasses.class_for_schemas( 
     | 
| 
      
 382 
     | 
    
         
            +
                        result_schema_class = JSI::SchemaClasses.class_for_schemas(result_schema_applied_schemas,
         
     | 
| 
      
 383 
     | 
    
         
            +
                          includes: SchemaClasses.includes_for(schema.jsi_node_content),
         
     | 
| 
      
 384 
     | 
    
         
            +
                          mutable: schema.jsi_mutable?,
         
     | 
| 
      
 385 
     | 
    
         
            +
                        )
         
     | 
| 
       283 
386 
     | 
    
         | 
| 
       284 
     | 
    
         
            -
                        result_schema_class.new( 
     | 
| 
       285 
     | 
    
         
            -
                          jsi_document: schema.jsi_document,
         
     | 
| 
      
 387 
     | 
    
         
            +
                        result_schema_class.new(schema.jsi_document,
         
     | 
| 
       286 
388 
     | 
    
         
             
                          jsi_ptr: schema.jsi_ptr,
         
     | 
| 
       287 
     | 
    
         
            -
                           
     | 
| 
      
 389 
     | 
    
         
            +
                          jsi_indicated_schemas: result_schema_indicated_schemas,
         
     | 
| 
       288 
390 
     | 
    
         
             
                          jsi_schema_base_uri: schema.jsi_schema_base_uri,
         
     | 
| 
       289 
391 
     | 
    
         
             
                          jsi_schema_resource_ancestors: schema.jsi_schema_resource_ancestors,
         
     | 
| 
      
 392 
     | 
    
         
            +
                          jsi_schema_registry: schema.jsi_schema_registry,
         
     | 
| 
      
 393 
     | 
    
         
            +
                          jsi_content_to_immutable: schema.jsi_content_to_immutable,
         
     | 
| 
      
 394 
     | 
    
         
            +
                          jsi_root_node: schema.jsi_ptr.root? ? nil : schema.jsi_root_node, # bad
         
     | 
| 
       290 
395 
     | 
    
         
             
                        )
         
     | 
| 
       291 
396 
     | 
    
         
             
                      else
         
     | 
| 
       292 
397 
     | 
    
         
             
                        raise(NotASchemaError, [
         
     | 
| 
         @@ -296,21 +401,62 @@ module JSI 
     | 
|
| 
       296 
401 
     | 
    
         
             
                      end
         
     | 
| 
       297 
402 
     | 
    
         
             
                    end
         
     | 
| 
       298 
403 
     | 
    
         
             
                  end
         
     | 
| 
      
 404 
     | 
    
         
            +
             
     | 
| 
      
 405 
     | 
    
         
            +
                  # Ensures the given param identifies a meta-schema and returns that meta-schema.
         
     | 
| 
      
 406 
     | 
    
         
            +
                  #
         
     | 
| 
      
 407 
     | 
    
         
            +
                  # @api private
         
     | 
| 
      
 408 
     | 
    
         
            +
                  # @param metaschema [Schema::MetaSchema, SchemaModule::MetaSchemaModule, #to_str]
         
     | 
| 
      
 409 
     | 
    
         
            +
                  # @raise [TypeError] if the param does not indicate a meta-schema
         
     | 
| 
      
 410 
     | 
    
         
            +
                  # @return [Base + Schema + Schema::MetaSchema]
         
     | 
| 
      
 411 
     | 
    
         
            +
                  def ensure_metaschema(metaschema, name: nil, schema_registry: JSI.schema_registry)
         
     | 
| 
      
 412 
     | 
    
         
            +
                    if metaschema.respond_to?(:to_str)
         
     | 
| 
      
 413 
     | 
    
         
            +
                      schema = Schema::Ref.new(metaschema, schema_registry: schema_registry).deref_schema
         
     | 
| 
      
 414 
     | 
    
         
            +
                      if !schema.describes_schema?
         
     | 
| 
      
 415 
     | 
    
         
            +
                        raise(TypeError, [name, "URI indicates a schema that is not a meta-schema: #{metaschema.pretty_inspect.chomp}"].compact.join(" "))
         
     | 
| 
      
 416 
     | 
    
         
            +
                      end
         
     | 
| 
      
 417 
     | 
    
         
            +
                      schema
         
     | 
| 
      
 418 
     | 
    
         
            +
                    elsif metaschema.is_a?(SchemaModule::MetaSchemaModule)
         
     | 
| 
      
 419 
     | 
    
         
            +
                      metaschema.schema
         
     | 
| 
      
 420 
     | 
    
         
            +
                    elsif metaschema.is_a?(Schema::MetaSchema)
         
     | 
| 
      
 421 
     | 
    
         
            +
                      metaschema
         
     | 
| 
      
 422 
     | 
    
         
            +
                    else
         
     | 
| 
      
 423 
     | 
    
         
            +
                      raise(TypeError, "#{name || "param"} does not indicate a meta-schema: #{metaschema.pretty_inspect.chomp}")
         
     | 
| 
      
 424 
     | 
    
         
            +
                    end
         
     | 
| 
      
 425 
     | 
    
         
            +
                  end
         
     | 
| 
      
 426 
     | 
    
         
            +
                end
         
     | 
| 
      
 427 
     | 
    
         
            +
             
     | 
| 
      
 428 
     | 
    
         
            +
                if Util::LAST_ARGUMENT_AS_KEYWORD_PARAMETERS
         
     | 
| 
      
 429 
     | 
    
         
            +
                  def initialize(*)
         
     | 
| 
      
 430 
     | 
    
         
            +
                    super
         
     | 
| 
      
 431 
     | 
    
         
            +
                    jsi_schema_initialize
         
     | 
| 
      
 432 
     | 
    
         
            +
                  end
         
     | 
| 
      
 433 
     | 
    
         
            +
                else
         
     | 
| 
      
 434 
     | 
    
         
            +
                  def initialize(*, **)
         
     | 
| 
      
 435 
     | 
    
         
            +
                    super
         
     | 
| 
      
 436 
     | 
    
         
            +
                    jsi_schema_initialize
         
     | 
| 
      
 437 
     | 
    
         
            +
                  end
         
     | 
| 
       299 
438 
     | 
    
         
             
                end
         
     | 
| 
       300 
439 
     | 
    
         | 
| 
       301 
440 
     | 
    
         
             
                # the underlying JSON data used to instantiate this JSI::Schema.
         
     | 
| 
       302 
     | 
    
         
            -
                # this is an alias for  
     | 
| 
      
 441 
     | 
    
         
            +
                # this is an alias for {Base#jsi_node_content}, named for clarity in the context of working with
         
     | 
| 
       303 
442 
     | 
    
         
             
                # a schema.
         
     | 
| 
       304 
443 
     | 
    
         
             
                def schema_content
         
     | 
| 
       305 
444 
     | 
    
         
             
                  jsi_node_content
         
     | 
| 
       306 
445 
     | 
    
         
             
                end
         
     | 
| 
       307 
446 
     | 
    
         | 
| 
      
 447 
     | 
    
         
            +
                # does this schema contain the given keyword?
         
     | 
| 
      
 448 
     | 
    
         
            +
                # @return [Boolean]
         
     | 
| 
      
 449 
     | 
    
         
            +
                def keyword?(keyword)
         
     | 
| 
      
 450 
     | 
    
         
            +
                  schema_content = jsi_node_content
         
     | 
| 
      
 451 
     | 
    
         
            +
                  schema_content.respond_to?(:to_hash) && schema_content.key?(keyword)
         
     | 
| 
      
 452 
     | 
    
         
            +
                end
         
     | 
| 
      
 453 
     | 
    
         
            +
             
     | 
| 
       308 
454 
     | 
    
         
             
                # the URI of this schema, calculated from our `#id`, resolved against our `#jsi_schema_base_uri`
         
     | 
| 
       309 
455 
     | 
    
         
             
                # @return [Addressable::URI, nil]
         
     | 
| 
       310 
456 
     | 
    
         
             
                def schema_absolute_uri
         
     | 
| 
       311 
457 
     | 
    
         
             
                  if respond_to?(:id_without_fragment) && id_without_fragment
         
     | 
| 
       312 
458 
     | 
    
         
             
                    if jsi_schema_base_uri
         
     | 
| 
       313 
     | 
    
         
            -
                       
     | 
| 
      
 459 
     | 
    
         
            +
                      jsi_schema_base_uri.join(id_without_fragment).freeze
         
     | 
| 
       314 
460 
     | 
    
         
             
                    elsif id_without_fragment.absolute?
         
     | 
| 
       315 
461 
     | 
    
         
             
                      id_without_fragment
         
     | 
| 
       316 
462 
     | 
    
         
             
                    else
         
     | 
| 
         @@ -321,7 +467,7 @@ module JSI 
     | 
|
| 
       321 
467 
     | 
    
         
             
                end
         
     | 
| 
       322 
468 
     | 
    
         | 
| 
       323 
469 
     | 
    
         
             
                # a nonrelative URI which refers to this schema.
         
     | 
| 
       324 
     | 
    
         
            -
                # nil if no  
     | 
| 
      
 470 
     | 
    
         
            +
                # `nil` if no ancestor of this schema defines an id.
         
     | 
| 
       325 
471 
     | 
    
         
             
                # see {#schema_uris} for all URIs known to refer to this schema.
         
     | 
| 
       326 
472 
     | 
    
         
             
                # @return [Addressable::URI, nil]
         
     | 
| 
       327 
473 
     | 
    
         
             
                def schema_uri
         
     | 
| 
         @@ -331,9 +477,11 @@ module JSI 
     | 
|
| 
       331 
477 
     | 
    
         
             
                # nonrelative URIs (that is, absolute, but possibly with a fragment) which refer to this schema
         
     | 
| 
       332 
478 
     | 
    
         
             
                # @return [Array<Addressable::URI>]
         
     | 
| 
       333 
479 
     | 
    
         
             
                def schema_uris
         
     | 
| 
       334 
     | 
    
         
            -
                   
     | 
| 
      
 480 
     | 
    
         
            +
                  @schema_uris_map[]
         
     | 
| 
      
 481 
     | 
    
         
            +
                end
         
     | 
| 
      
 482 
     | 
    
         
            +
             
     | 
| 
      
 483 
     | 
    
         
            +
                private def schema_uris_compute(**_) # TODO remove **_ eventually (keyword argument compatibility)
         
     | 
| 
       335 
484 
     | 
    
         
             
                    each_schema_uri.to_a
         
     | 
| 
       336 
     | 
    
         
            -
                  end
         
     | 
| 
       337 
485 
     | 
    
         
             
                end
         
     | 
| 
       338 
486 
     | 
    
         | 
| 
       339 
487 
     | 
    
         
             
                # see {#schema_uris}
         
     | 
| 
         @@ -344,22 +492,22 @@ module JSI 
     | 
|
| 
       344 
492 
     | 
    
         | 
| 
       345 
493 
     | 
    
         
             
                  yield schema_absolute_uri if schema_absolute_uri
         
     | 
| 
       346 
494 
     | 
    
         | 
| 
       347 
     | 
    
         
            -
                   
     | 
| 
       348 
     | 
    
         
            -
                    resource. 
     | 
| 
      
 495 
     | 
    
         
            +
                  ancestor_schemas = jsi_subschema_resource_ancestors.reverse_each.select do |resource|
         
     | 
| 
      
 496 
     | 
    
         
            +
                    resource.schema_absolute_uri
         
     | 
| 
       349 
497 
     | 
    
         
             
                  end
         
     | 
| 
       350 
498 
     | 
    
         | 
| 
       351 
     | 
    
         
            -
                  anchored =  
     | 
| 
       352 
     | 
    
         
            -
                   
     | 
| 
      
 499 
     | 
    
         
            +
                  anchored = respond_to?(:anchor) ? anchor : nil
         
     | 
| 
      
 500 
     | 
    
         
            +
                  ancestor_schemas.each do |ancestor_schema|
         
     | 
| 
       353 
501 
     | 
    
         
             
                    if anchored
         
     | 
| 
       354 
     | 
    
         
            -
                      if  
     | 
| 
       355 
     | 
    
         
            -
                        yield 
     | 
| 
      
 502 
     | 
    
         
            +
                      if ancestor_schema.jsi_anchor_subschema(anchor) == self
         
     | 
| 
      
 503 
     | 
    
         
            +
                        yield(ancestor_schema.schema_absolute_uri.merge(fragment: anchor).freeze)
         
     | 
| 
       356 
504 
     | 
    
         
             
                      else
         
     | 
| 
       357 
505 
     | 
    
         
             
                        anchored = false
         
     | 
| 
       358 
506 
     | 
    
         
             
                      end
         
     | 
| 
       359 
507 
     | 
    
         
             
                    end
         
     | 
| 
       360 
508 
     | 
    
         | 
| 
       361 
     | 
    
         
            -
                    relative_ptr =  
     | 
| 
       362 
     | 
    
         
            -
                    yield 
     | 
| 
      
 509 
     | 
    
         
            +
                    relative_ptr = jsi_ptr.relative_to(ancestor_schema.jsi_ptr)
         
     | 
| 
      
 510 
     | 
    
         
            +
                    yield(ancestor_schema.schema_absolute_uri.merge(fragment: relative_ptr.fragment).freeze)
         
     | 
| 
       363 
511 
     | 
    
         
             
                  end
         
     | 
| 
       364 
512 
     | 
    
         | 
| 
       365 
513 
     | 
    
         
             
                  nil
         
     | 
| 
         @@ -368,9 +516,6 @@ module JSI 
     | 
|
| 
       368 
516 
     | 
    
         
             
                # a module which extends all instances of this schema. this may be opened by the application to add
         
     | 
| 
       369 
517 
     | 
    
         
             
                # methods to schema instances.
         
     | 
| 
       370 
518 
     | 
    
         
             
                #
         
     | 
| 
       371 
     | 
    
         
            -
                # this module includes accessor methods for object property names this schema
         
     | 
| 
       372 
     | 
    
         
            -
                # describes (see {#described_object_property_names}). these accessors wrap {Base#[]} and {Base#[]=}.
         
     | 
| 
       373 
     | 
    
         
            -
                #
         
     | 
| 
       374 
519 
     | 
    
         
             
                # some functionality is also defined on the module itself (its singleton class, not for its instances):
         
     | 
| 
       375 
520 
     | 
    
         
             
                #
         
     | 
| 
       376 
521 
     | 
    
         
             
                # - the module is extended with {JSI::SchemaModule}, which defines .new_jsi to instantiate instances
         
     | 
| 
         @@ -380,7 +525,7 @@ module JSI 
     | 
|
| 
       380 
525 
     | 
    
         
             
                #   as `schema.items.jsi_schema_module`.
         
     | 
| 
       381 
526 
     | 
    
         
             
                # - method .schema which returns this schema.
         
     | 
| 
       382 
527 
     | 
    
         
             
                #
         
     | 
| 
       383 
     | 
    
         
            -
                # @return [ 
     | 
| 
      
 528 
     | 
    
         
            +
                # @return [SchemaModule]
         
     | 
| 
       384 
529 
     | 
    
         
             
                def jsi_schema_module
         
     | 
| 
       385 
530 
     | 
    
         
             
                  JSI::SchemaClasses.module_for_schema(self)
         
     | 
| 
       386 
531 
     | 
    
         
             
                end
         
     | 
| 
         @@ -395,56 +540,79 @@ module JSI 
     | 
|
| 
       395 
540 
     | 
    
         
             
                  jsi_schema_module.module_exec(*a, **kw, &block)
         
     | 
| 
       396 
541 
     | 
    
         
             
                end
         
     | 
| 
       397 
542 
     | 
    
         | 
| 
       398 
     | 
    
         
            -
                #  
     | 
| 
       399 
     | 
    
         
            -
                 
     | 
| 
       400 
     | 
    
         
            -
             
     | 
| 
       401 
     | 
    
         
            -
                end
         
     | 
| 
       402 
     | 
    
         
            -
             
     | 
| 
       403 
     | 
    
         
            -
                # instantiates the given instance as a JSI::Base class for schemas matched from this schema to the
         
     | 
| 
       404 
     | 
    
         
            -
                # instance.
         
     | 
| 
      
 543 
     | 
    
         
            +
                # Instantiates a new JSI whose content comes from the given `instance` param.
         
     | 
| 
      
 544 
     | 
    
         
            +
                # This schema indicates the schemas of the JSI - its schemas are inplace
         
     | 
| 
      
 545 
     | 
    
         
            +
                # applicators of this schema which apply to the given instance.
         
     | 
| 
       405 
546 
     | 
    
         
             
                #
         
     | 
| 
       406 
     | 
    
         
            -
                # @param  
     | 
| 
       407 
     | 
    
         
            -
                # @ 
     | 
| 
       408 
     | 
    
         
            -
                #  
     | 
| 
       409 
     | 
    
         
            -
                 
     | 
| 
       410 
     | 
    
         
            -
                def new_jsi(instance,
         
     | 
| 
       411 
     | 
    
         
            -
                    **kw
         
     | 
| 
       412 
     | 
    
         
            -
                )
         
     | 
| 
      
 547 
     | 
    
         
            +
                # @param (see SchemaSet#new_jsi)
         
     | 
| 
      
 548 
     | 
    
         
            +
                # @return [JSI::Base subclass] a JSI whose content comes from the given instance and whose schemas are
         
     | 
| 
      
 549 
     | 
    
         
            +
                #   inplace applicators of this schema.
         
     | 
| 
      
 550 
     | 
    
         
            +
                def new_jsi(instance, **kw)
         
     | 
| 
       413 
551 
     | 
    
         
             
                  SchemaSet[self].new_jsi(instance, **kw)
         
     | 
| 
       414 
552 
     | 
    
         
             
                end
         
     | 
| 
       415 
553 
     | 
    
         | 
| 
       416 
     | 
    
         
            -
                #  
     | 
| 
      
 554 
     | 
    
         
            +
                # @param keyword schema keyword e.g. "$ref", "$schema"
         
     | 
| 
      
 555 
     | 
    
         
            +
                # @return [Schema::Ref]
         
     | 
| 
      
 556 
     | 
    
         
            +
                def schema_ref(keyword = "$ref")
         
     | 
| 
      
 557 
     | 
    
         
            +
                  raise(ArgumentError, "keyword not present: #{keyword}") unless keyword?(keyword)
         
     | 
| 
      
 558 
     | 
    
         
            +
                  @schema_ref_map[keyword: keyword, value: schema_content[keyword]]
         
     | 
| 
      
 559 
     | 
    
         
            +
                end
         
     | 
| 
      
 560 
     | 
    
         
            +
             
     | 
| 
      
 561 
     | 
    
         
            +
                # Does this schema itself describe a schema? I.e. is this schema a meta-schema?
         
     | 
| 
       417 
562 
     | 
    
         
             
                # @return [Boolean]
         
     | 
| 
       418 
563 
     | 
    
         
             
                def describes_schema?
         
     | 
| 
       419 
     | 
    
         
            -
                   
     | 
| 
      
 564 
     | 
    
         
            +
                  jsi_schema_module <= JSI::Schema || false
         
     | 
| 
       420 
565 
     | 
    
         
             
                end
         
     | 
| 
       421 
566 
     | 
    
         | 
| 
       422 
     | 
    
         
            -
                #  
     | 
| 
       423 
     | 
    
         
            -
                #  
     | 
| 
       424 
     | 
    
         
            -
                 
     | 
| 
       425 
     | 
    
         
            -
             
     | 
| 
       426 
     | 
    
         
            -
                  return @jsi_schema_instance_modules if instance_variable_defined?(:@jsi_schema_instance_modules)
         
     | 
| 
       427 
     | 
    
         
            -
                  return Set[].freeze
         
     | 
| 
      
 567 
     | 
    
         
            +
                # Is this a JSI Schema?
         
     | 
| 
      
 568 
     | 
    
         
            +
                # @return [Boolean]
         
     | 
| 
      
 569 
     | 
    
         
            +
                def jsi_is_schema?
         
     | 
| 
      
 570 
     | 
    
         
            +
                  true
         
     | 
| 
       428 
571 
     | 
    
         
             
                end
         
     | 
| 
       429 
572 
     | 
    
         | 
| 
       430 
     | 
    
         
            -
                #  
     | 
| 
      
 573 
     | 
    
         
            +
                # Indicates that this schema describes schemas, i.e. it is a meta-schema.
         
     | 
| 
      
 574 
     | 
    
         
            +
                # this schema is extended with {Schema::MetaSchema} and its {#jsi_schema_module} is extended
         
     | 
| 
      
 575 
     | 
    
         
            +
                # with {SchemaModule::MetaSchemaModule}, and the JSI Schema Module will include
         
     | 
| 
      
 576 
     | 
    
         
            +
                # JSI::Schema and the given modules.
         
     | 
| 
       431 
577 
     | 
    
         
             
                #
         
     | 
| 
      
 578 
     | 
    
         
            +
                # @param schema_implementation_modules [Enumerable<Module>] modules which implement the functionality of
         
     | 
| 
      
 579 
     | 
    
         
            +
                #   the schema to extend schemas described by this schema.
         
     | 
| 
       432 
580 
     | 
    
         
             
                # @return [void]
         
     | 
| 
       433 
     | 
    
         
            -
                def  
     | 
| 
       434 
     | 
    
         
            -
                   
     | 
| 
      
 581 
     | 
    
         
            +
                def describes_schema!(schema_implementation_modules)
         
     | 
| 
      
 582 
     | 
    
         
            +
                  schema_implementation_modules = Util.ensure_module_set(schema_implementation_modules)
         
     | 
| 
      
 583 
     | 
    
         
            +
             
     | 
| 
      
 584 
     | 
    
         
            +
                  if describes_schema?
         
     | 
| 
      
 585 
     | 
    
         
            +
                    # this schema, or one equal to it, has already had describes_schema! called on it.
         
     | 
| 
      
 586 
     | 
    
         
            +
                    # this is to be avoided, but is not particularly a problem.
         
     | 
| 
      
 587 
     | 
    
         
            +
                    # it is a bug if it was called different times with different schema_implementation_modules, though.
         
     | 
| 
      
 588 
     | 
    
         
            +
                    unless jsi_schema_module.schema_implementation_modules == schema_implementation_modules
         
     | 
| 
      
 589 
     | 
    
         
            +
                      raise(ArgumentError, "this schema already describes a schema with different schema_implementation_modules")
         
     | 
| 
      
 590 
     | 
    
         
            +
                    end
         
     | 
| 
      
 591 
     | 
    
         
            +
                  else
         
     | 
| 
      
 592 
     | 
    
         
            +
                    jsi_schema_module.include(Schema)
         
     | 
| 
      
 593 
     | 
    
         
            +
                    schema_implementation_modules.each do |mod|
         
     | 
| 
      
 594 
     | 
    
         
            +
                      jsi_schema_module.include(mod)
         
     | 
| 
      
 595 
     | 
    
         
            +
                    end
         
     | 
| 
      
 596 
     | 
    
         
            +
                    jsi_schema_module.extend(SchemaModule::MetaSchemaModule)
         
     | 
| 
      
 597 
     | 
    
         
            +
                  end
         
     | 
| 
      
 598 
     | 
    
         
            +
             
     | 
| 
      
 599 
     | 
    
         
            +
                  @schema_implementation_modules = schema_implementation_modules
         
     | 
| 
      
 600 
     | 
    
         
            +
                  extend(Schema::MetaSchema)
         
     | 
| 
      
 601 
     | 
    
         
            +
             
     | 
| 
      
 602 
     | 
    
         
            +
                  nil
         
     | 
| 
       435 
603 
     | 
    
         
             
                end
         
     | 
| 
       436 
604 
     | 
    
         | 
| 
       437 
605 
     | 
    
         
             
                # a resource containing this schema.
         
     | 
| 
       438 
606 
     | 
    
         
             
                #
         
     | 
| 
       439 
     | 
    
         
            -
                #  
     | 
| 
      
 607 
     | 
    
         
            +
                # If any ancestor, or this schema itself, is a schema with an absolute uri (see {#schema_absolute_uri}),
         
     | 
| 
       440 
608 
     | 
    
         
             
                # the resource root is the closest schema with an absolute uri.
         
     | 
| 
       441 
609 
     | 
    
         
             
                #
         
     | 
| 
       442 
     | 
    
         
            -
                #  
     | 
| 
       443 
     | 
    
         
            -
                #  
     | 
| 
      
 610 
     | 
    
         
            +
                # If no ancestor schema has an absolute uri, the schema_resource_root is the {Base#jsi_root_node document's root node}.
         
     | 
| 
      
 611 
     | 
    
         
            +
                # In this case, the resource root may or may not be a schema itself.
         
     | 
| 
       444 
612 
     | 
    
         
             
                #
         
     | 
| 
       445 
613 
     | 
    
         
             
                # @return [JSI::Base] resource containing this schema
         
     | 
| 
       446 
614 
     | 
    
         
             
                def schema_resource_root
         
     | 
| 
       447 
     | 
    
         
            -
                  jsi_subschema_resource_ancestors. 
     | 
| 
      
 615 
     | 
    
         
            +
                  jsi_subschema_resource_ancestors.last || jsi_root_node
         
     | 
| 
       448 
616 
     | 
    
         
             
                end
         
     | 
| 
       449 
617 
     | 
    
         | 
| 
       450 
618 
     | 
    
         
             
                # is this schema the root of a schema resource?
         
     | 
| 
         @@ -458,73 +626,95 @@ module JSI 
     | 
|
| 
       458 
626 
     | 
    
         
             
                # @param subptr [JSI::Ptr, #to_ary] a relative pointer, or array of tokens, pointing to the subschema
         
     | 
| 
       459 
627 
     | 
    
         
             
                # @return [JSI::Schema] the subschema at the location indicated by subptr. self if subptr is empty.
         
     | 
| 
       460 
628 
     | 
    
         
             
                def subschema(subptr)
         
     | 
| 
       461 
     | 
    
         
            -
                  subschema_map[Ptr.ary_ptr(subptr)]
         
     | 
| 
      
 629 
     | 
    
         
            +
                  @subschema_map[subptr: Ptr.ary_ptr(subptr)]
         
     | 
| 
       462 
630 
     | 
    
         
             
                end
         
     | 
| 
       463 
631 
     | 
    
         | 
| 
       464 
     | 
    
         
            -
                private
         
     | 
| 
       465 
     | 
    
         
            -
             
     | 
| 
       466 
     | 
    
         
            -
                def subschema_map
         
     | 
| 
       467 
     | 
    
         
            -
                  jsi_memomap(:subschema) do |subptr|
         
     | 
| 
       468 
     | 
    
         
            -
                    if is_a?(MetaschemaNode::BootstrapSchema)
         
     | 
| 
       469 
     | 
    
         
            -
                      self.class.new(
         
     | 
| 
       470 
     | 
    
         
            -
                        jsi_document,
         
     | 
| 
       471 
     | 
    
         
            -
                        jsi_ptr: jsi_ptr + subptr,
         
     | 
| 
       472 
     | 
    
         
            -
                        jsi_schema_base_uri: jsi_resource_ancestor_uri,
         
     | 
| 
       473 
     | 
    
         
            -
                      )
         
     | 
| 
       474 
     | 
    
         
            -
                    else
         
     | 
| 
       475 
     | 
    
         
            -
                      Schema.ensure_schema(subptr.evaluate(self, as_jsi: true), msg: [
         
     | 
| 
      
 632 
     | 
    
         
            +
                private def subschema_compute(subptr: )
         
     | 
| 
      
 633 
     | 
    
         
            +
                      Schema.ensure_schema(jsi_descendent_node(subptr), msg: [
         
     | 
| 
       476 
634 
     | 
    
         
             
                        "subschema is not a schema at pointer: #{subptr.pointer}"
         
     | 
| 
       477 
635 
     | 
    
         
             
                      ])
         
     | 
| 
       478 
     | 
    
         
            -
                    end
         
     | 
| 
       479 
     | 
    
         
            -
                  end
         
     | 
| 
       480 
636 
     | 
    
         
             
                end
         
     | 
| 
       481 
637 
     | 
    
         | 
| 
       482 
     | 
    
         
            -
                 
     | 
| 
       483 
     | 
    
         
            -
             
     | 
| 
       484 
     | 
    
         
            -
                # a schema in the same schema resource as this one (see #schema_resource_root) at the given
         
     | 
| 
      
 638 
     | 
    
         
            +
                # a schema in the same schema resource as this one (see {#schema_resource_root}) at the given
         
     | 
| 
       485 
639 
     | 
    
         
             
                # pointer relative to the root of the schema resource.
         
     | 
| 
       486 
640 
     | 
    
         
             
                #
         
     | 
| 
       487 
641 
     | 
    
         
             
                # @param ptr [JSI::Ptr, #to_ary] a pointer to a schema from our schema resource root
         
     | 
| 
       488 
642 
     | 
    
         
             
                # @return [JSI::Schema] the schema pointed to by ptr
         
     | 
| 
       489 
643 
     | 
    
         
             
                def resource_root_subschema(ptr)
         
     | 
| 
       490 
     | 
    
         
            -
                  resource_root_subschema_map[Ptr.ary_ptr(ptr)]
         
     | 
| 
      
 644 
     | 
    
         
            +
                  @resource_root_subschema_map[ptr: Ptr.ary_ptr(ptr)]
         
     | 
| 
       491 
645 
     | 
    
         
             
                end
         
     | 
| 
       492 
646 
     | 
    
         | 
| 
       493 
     | 
    
         
            -
                private
         
     | 
| 
       494 
     | 
    
         
            -
             
     | 
| 
       495 
     | 
    
         
            -
             
     | 
| 
       496 
     | 
    
         
            -
                  jsi_memomap(:resource_root_subschema_map) do |ptr|
         
     | 
| 
       497 
     | 
    
         
            -
                    schema = self
         
     | 
| 
       498 
     | 
    
         
            -
                    if schema.is_a?(MetaschemaNode::BootstrapSchema)
         
     | 
| 
       499 
     | 
    
         
            -
                      # BootstrapSchema does not track jsi_schema_resource_ancestors used by #schema_resource_root;
         
     | 
| 
       500 
     | 
    
         
            -
                      # resource_root_subschema is always relative to the document root.
         
     | 
| 
       501 
     | 
    
         
            -
                      # BootstrapSchema also does not implement jsi_root_node or #[]. we instantiate the ptr directly
         
     | 
| 
       502 
     | 
    
         
            -
                      # rather than as a subschema from the root.
         
     | 
| 
       503 
     | 
    
         
            -
                      schema.class.new(
         
     | 
| 
       504 
     | 
    
         
            -
                        schema.jsi_document,
         
     | 
| 
       505 
     | 
    
         
            -
                        jsi_ptr: ptr,
         
     | 
| 
       506 
     | 
    
         
            -
                        jsi_schema_base_uri: nil,
         
     | 
| 
       507 
     | 
    
         
            -
                      )
         
     | 
| 
       508 
     | 
    
         
            -
                    else
         
     | 
| 
       509 
     | 
    
         
            -
                      resource_root = schema.schema_resource_root
         
     | 
| 
       510 
     | 
    
         
            -
                      Schema.ensure_schema(ptr.evaluate(resource_root, as_jsi: true),
         
     | 
| 
       511 
     | 
    
         
            -
                        msg: [
         
     | 
| 
       512 
     | 
    
         
            -
                          "subschema is not a schema at pointer: #{ptr.pointer}"
         
     | 
| 
       513 
     | 
    
         
            -
                        ],
         
     | 
| 
       514 
     | 
    
         
            -
                        reinstantiate_as: schema.jsi_schemas.select(&:describes_schema?)
         
     | 
| 
      
 647 
     | 
    
         
            +
                private def resource_root_subschema_compute(ptr: )
         
     | 
| 
      
 648 
     | 
    
         
            +
                      Schema.ensure_schema(schema_resource_root.jsi_descendent_node(ptr),
         
     | 
| 
      
 649 
     | 
    
         
            +
                        reinstantiate_as: jsi_schemas.select(&:describes_schema?)
         
     | 
| 
       515 
650 
     | 
    
         
             
                      )
         
     | 
| 
       516 
     | 
    
         
            -
             
     | 
| 
      
 651 
     | 
    
         
            +
                end
         
     | 
| 
      
 652 
     | 
    
         
            +
             
     | 
| 
      
 653 
     | 
    
         
            +
                # a set of inplace applicator schemas of this schema (from $ref, allOf, etc.) which apply to the
         
     | 
| 
      
 654 
     | 
    
         
            +
                # given instance.
         
     | 
| 
      
 655 
     | 
    
         
            +
                #
         
     | 
| 
      
 656 
     | 
    
         
            +
                # the returned set will contain this schema itself, unless this schema contains a $ref keyword.
         
     | 
| 
      
 657 
     | 
    
         
            +
                #
         
     | 
| 
      
 658 
     | 
    
         
            +
                # @param instance [Object] the instance to check any applicators against
         
     | 
| 
      
 659 
     | 
    
         
            +
                # @return [JSI::SchemaSet] matched applicator schemas
         
     | 
| 
      
 660 
     | 
    
         
            +
                def inplace_applicator_schemas(instance)
         
     | 
| 
      
 661 
     | 
    
         
            +
                  SchemaSet.new(each_inplace_applicator_schema(instance))
         
     | 
| 
      
 662 
     | 
    
         
            +
                end
         
     | 
| 
      
 663 
     | 
    
         
            +
             
     | 
| 
      
 664 
     | 
    
         
            +
                # yields each inplace applicator schema which applies to the given instance.
         
     | 
| 
      
 665 
     | 
    
         
            +
                #
         
     | 
| 
      
 666 
     | 
    
         
            +
                # @param instance (see #inplace_applicator_schemas)
         
     | 
| 
      
 667 
     | 
    
         
            +
                # @param visited_refs [Enumerable<JSI::Schema::Ref>]
         
     | 
| 
      
 668 
     | 
    
         
            +
                # @yield [JSI::Schema]
         
     | 
| 
      
 669 
     | 
    
         
            +
                # @return [nil, Enumerator] an Enumerator if invoked without a block; otherwise nil
         
     | 
| 
      
 670 
     | 
    
         
            +
                def each_inplace_applicator_schema(
         
     | 
| 
      
 671 
     | 
    
         
            +
                    instance,
         
     | 
| 
      
 672 
     | 
    
         
            +
                    visited_refs: Util::EMPTY_ARY,
         
     | 
| 
      
 673 
     | 
    
         
            +
                    &block
         
     | 
| 
      
 674 
     | 
    
         
            +
                )
         
     | 
| 
      
 675 
     | 
    
         
            +
                  return to_enum(__method__, instance, visited_refs: visited_refs) unless block
         
     | 
| 
      
 676 
     | 
    
         
            +
             
     | 
| 
      
 677 
     | 
    
         
            +
                  catch(:jsi_application_done) do
         
     | 
| 
      
 678 
     | 
    
         
            +
                    internal_inplace_applicate_keywords(instance, visited_refs, &block)
         
     | 
| 
       517 
679 
     | 
    
         
             
                  end
         
     | 
| 
      
 680 
     | 
    
         
            +
             
     | 
| 
      
 681 
     | 
    
         
            +
                  nil
         
     | 
| 
       518 
682 
     | 
    
         
             
                end
         
     | 
| 
       519 
683 
     | 
    
         | 
| 
       520 
     | 
    
         
            -
                 
     | 
| 
      
 684 
     | 
    
         
            +
                # a set of child applicator subschemas of this schema which apply to the child of the given instance
         
     | 
| 
      
 685 
     | 
    
         
            +
                # on the given token.
         
     | 
| 
      
 686 
     | 
    
         
            +
                #
         
     | 
| 
      
 687 
     | 
    
         
            +
                # @param token [Object] the array index or object property name for the child instance
         
     | 
| 
      
 688 
     | 
    
         
            +
                # @param instance [Object] the instance to check any child applicators against
         
     | 
| 
      
 689 
     | 
    
         
            +
                # @return [JSI::SchemaSet] child applicator subschemas of this schema for the given token
         
     | 
| 
      
 690 
     | 
    
         
            +
                #   of the instance
         
     | 
| 
      
 691 
     | 
    
         
            +
                def child_applicator_schemas(token, instance)
         
     | 
| 
      
 692 
     | 
    
         
            +
                  SchemaSet.new(each_child_applicator_schema(token, instance))
         
     | 
| 
      
 693 
     | 
    
         
            +
                end
         
     | 
| 
      
 694 
     | 
    
         
            +
             
     | 
| 
      
 695 
     | 
    
         
            +
                # yields each child applicator subschema (from properties, items, etc.) which applies to the child of
         
     | 
| 
      
 696 
     | 
    
         
            +
                # the given instance on the given token.
         
     | 
| 
      
 697 
     | 
    
         
            +
                #
         
     | 
| 
      
 698 
     | 
    
         
            +
                # @param (see #child_applicator_schemas)
         
     | 
| 
      
 699 
     | 
    
         
            +
                # @yield [JSI::Schema]
         
     | 
| 
      
 700 
     | 
    
         
            +
                # @return [nil, Enumerator] an Enumerator if invoked without a block; otherwise nil
         
     | 
| 
      
 701 
     | 
    
         
            +
                def each_child_applicator_schema(token, instance, &block)
         
     | 
| 
      
 702 
     | 
    
         
            +
                  return to_enum(__method__, token, instance) unless block
         
     | 
| 
      
 703 
     | 
    
         
            +
             
     | 
| 
      
 704 
     | 
    
         
            +
                  internal_child_applicate_keywords(token, instance, &block)
         
     | 
| 
      
 705 
     | 
    
         
            +
             
     | 
| 
      
 706 
     | 
    
         
            +
                  nil
         
     | 
| 
      
 707 
     | 
    
         
            +
                end
         
     | 
| 
       521 
708 
     | 
    
         | 
| 
       522 
709 
     | 
    
         
             
                # any object property names this schema indicates may be present on its instances.
         
     | 
| 
       523 
710 
     | 
    
         
             
                # this includes any keys of this schema's "properties" object and any entries of this schema's
         
     | 
| 
       524 
711 
     | 
    
         
             
                # array of "required" property keys.
         
     | 
| 
       525 
712 
     | 
    
         
             
                # @return [Set]
         
     | 
| 
       526 
713 
     | 
    
         
             
                def described_object_property_names
         
     | 
| 
       527 
     | 
    
         
            -
                   
     | 
| 
      
 714 
     | 
    
         
            +
                  @described_object_property_names_map[]
         
     | 
| 
      
 715 
     | 
    
         
            +
                end
         
     | 
| 
      
 716 
     | 
    
         
            +
             
     | 
| 
      
 717 
     | 
    
         
            +
                private def described_object_property_names_compute(**_) # TODO remove **_ eventually (keyword argument compatibility)
         
     | 
| 
       528 
718 
     | 
    
         
             
                    Set.new.tap do |property_names|
         
     | 
| 
       529 
719 
     | 
    
         
             
                      if schema_content.respond_to?(:to_hash) && schema_content['properties'].respond_to?(:to_hash)
         
     | 
| 
       530 
720 
     | 
    
         
             
                        property_names.merge(schema_content['properties'].keys)
         
     | 
| 
         @@ -533,7 +723,6 @@ module JSI 
     | 
|
| 
       533 
723 
     | 
    
         
             
                        property_names.merge(schema_content['required'].to_ary)
         
     | 
| 
       534 
724 
     | 
    
         
             
                      end
         
     | 
| 
       535 
725 
     | 
    
         
             
                    end.freeze
         
     | 
| 
       536 
     | 
    
         
            -
                  end
         
     | 
| 
       537 
726 
     | 
    
         
             
                end
         
     | 
| 
       538 
727 
     | 
    
         | 
| 
       539 
728 
     | 
    
         
             
                # validates the given instance against this schema
         
     | 
| 
         @@ -541,7 +730,7 @@ module JSI 
     | 
|
| 
       541 
730 
     | 
    
         
             
                # @param instance [Object] the instance to validate against this schema
         
     | 
| 
       542 
731 
     | 
    
         
             
                # @return [JSI::Validation::Result]
         
     | 
| 
       543 
732 
     | 
    
         
             
                def instance_validate(instance)
         
     | 
| 
       544 
     | 
    
         
            -
                  if instance.is_a?( 
     | 
| 
      
 733 
     | 
    
         
            +
                  if instance.is_a?(SchemaAncestorNode)
         
     | 
| 
       545 
734 
     | 
    
         
             
                    instance_ptr = instance.jsi_ptr
         
     | 
| 
       546 
735 
     | 
    
         
             
                    instance_document = instance.jsi_document
         
     | 
| 
       547 
736 
     | 
    
         
             
                  else
         
     | 
| 
         @@ -555,52 +744,80 @@ module JSI 
     | 
|
| 
       555 
744 
     | 
    
         
             
                # @param instance [Object] the instance to validate against this schema
         
     | 
| 
       556 
745 
     | 
    
         
             
                # @return [Boolean]
         
     | 
| 
       557 
746 
     | 
    
         
             
                def instance_valid?(instance)
         
     | 
| 
       558 
     | 
    
         
            -
                  if instance.is_a?( 
     | 
| 
      
 747 
     | 
    
         
            +
                  if instance.is_a?(SchemaAncestorNode)
         
     | 
| 
       559 
748 
     | 
    
         
             
                    instance = instance.jsi_node_content
         
     | 
| 
       560 
749 
     | 
    
         
             
                  end
         
     | 
| 
       561 
750 
     | 
    
         
             
                  internal_validate_instance(Ptr[], instance, validate_only: true).valid?
         
     | 
| 
       562 
751 
     | 
    
         
             
                end
         
     | 
| 
       563 
752 
     | 
    
         | 
| 
      
 753 
     | 
    
         
            +
                # validates the given instance against this schema
         
     | 
| 
      
 754 
     | 
    
         
            +
                #
         
     | 
| 
       564 
755 
     | 
    
         
             
                # @private
         
     | 
| 
       565 
     | 
    
         
            -
                 
     | 
| 
       566 
     | 
    
         
            -
             
     | 
| 
       567 
     | 
    
         
            -
                 
     | 
| 
       568 
     | 
    
         
            -
             
     | 
| 
       569 
     | 
    
         
            -
                # @ 
     | 
| 
       570 
     | 
    
         
            -
                def  
     | 
| 
       571 
     | 
    
         
            -
             
     | 
| 
       572 
     | 
    
         
            -
             
     | 
| 
       573 
     | 
    
         
            -
             
     | 
| 
       574 
     | 
    
         
            -
             
     | 
| 
       575 
     | 
    
         
            -
                 
     | 
| 
       576 
     | 
    
         
            -
                   
     | 
| 
       577 
     | 
    
         
            -
             
     | 
| 
       578 
     | 
    
         
            -
             
     | 
| 
       579 
     | 
    
         
            -
             
     | 
| 
       580 
     | 
    
         
            -
             
     | 
| 
       581 
     | 
    
         
            -
                   
     | 
| 
       582 
     | 
    
         
            -
             
     | 
| 
       583 
     | 
    
         
            -
             
     | 
| 
       584 
     | 
    
         
            -
             
     | 
| 
       585 
     | 
    
         
            -
             
     | 
| 
       586 
     | 
    
         
            -
             
     | 
| 
       587 
     | 
    
         
            -
             
     | 
| 
      
 756 
     | 
    
         
            +
                # @param instance_ptr [JSI::Ptr] a pointer to the instance to validate against the schema, in the instance_document
         
     | 
| 
      
 757 
     | 
    
         
            +
                # @param instance_document [#to_hash, #to_ary, Object] document containing the instance instance_ptr pointer points to
         
     | 
| 
      
 758 
     | 
    
         
            +
                # @param validate_only [Boolean] whether to return a full schema validation result or a simple, validation-only result
         
     | 
| 
      
 759 
     | 
    
         
            +
                # @param visited_refs [Enumerable<JSI::Schema::Ref>]
         
     | 
| 
      
 760 
     | 
    
         
            +
                # @return [JSI::Validation::Result]
         
     | 
| 
      
 761 
     | 
    
         
            +
                def internal_validate_instance(
         
     | 
| 
      
 762 
     | 
    
         
            +
                    instance_ptr,
         
     | 
| 
      
 763 
     | 
    
         
            +
                    instance_document,
         
     | 
| 
      
 764 
     | 
    
         
            +
                    visited_refs: Util::EMPTY_ARY,
         
     | 
| 
      
 765 
     | 
    
         
            +
                    validate_only: false
         
     | 
| 
      
 766 
     | 
    
         
            +
                )
         
     | 
| 
      
 767 
     | 
    
         
            +
                  if validate_only
         
     | 
| 
      
 768 
     | 
    
         
            +
                    result = JSI::Validation::VALID
         
     | 
| 
      
 769 
     | 
    
         
            +
                  else
         
     | 
| 
      
 770 
     | 
    
         
            +
                    result = JSI::Validation::FullResult.new
         
     | 
| 
      
 771 
     | 
    
         
            +
                  end
         
     | 
| 
      
 772 
     | 
    
         
            +
                  result_builder = result.class::Builder.new(
         
     | 
| 
      
 773 
     | 
    
         
            +
                    result: result,
         
     | 
| 
      
 774 
     | 
    
         
            +
                    schema: self,
         
     | 
| 
      
 775 
     | 
    
         
            +
                    instance_ptr: instance_ptr,
         
     | 
| 
      
 776 
     | 
    
         
            +
                    instance_document: instance_document,
         
     | 
| 
      
 777 
     | 
    
         
            +
                    validate_only: validate_only,
         
     | 
| 
      
 778 
     | 
    
         
            +
                    visited_refs: visited_refs,
         
     | 
| 
      
 779 
     | 
    
         
            +
                  )
         
     | 
| 
       588 
780 
     | 
    
         | 
| 
       589 
     | 
    
         
            -
             
     | 
| 
       590 
     | 
    
         
            -
             
     | 
| 
       591 
     | 
    
         
            -
             
     | 
| 
      
 781 
     | 
    
         
            +
                  catch(:jsi_validation_result) do
         
     | 
| 
      
 782 
     | 
    
         
            +
                    # note: true/false are not valid as schemas in draft 4; they are only values of
         
     | 
| 
      
 783 
     | 
    
         
            +
                    # additionalProperties / additionalItems. since their behavior is undefined, though,
         
     | 
| 
      
 784 
     | 
    
         
            +
                    # it's fine for them to behave the same as boolean schemas in later drafts.
         
     | 
| 
      
 785 
     | 
    
         
            +
                    # I don't care about draft 4 to implement a different structuring for that.
         
     | 
| 
      
 786 
     | 
    
         
            +
                    if schema_content == true
         
     | 
| 
      
 787 
     | 
    
         
            +
                      # noop
         
     | 
| 
      
 788 
     | 
    
         
            +
                    elsif schema_content == false
         
     | 
| 
      
 789 
     | 
    
         
            +
                      result_builder.validate(false, 'instance is not valid against `false` schema')
         
     | 
| 
      
 790 
     | 
    
         
            +
                    elsif schema_content.respond_to?(:to_hash)
         
     | 
| 
      
 791 
     | 
    
         
            +
                      internal_validate_keywords(result_builder)
         
     | 
| 
      
 792 
     | 
    
         
            +
                    else
         
     | 
| 
      
 793 
     | 
    
         
            +
                      result_builder.schema_error('schema is not a boolean or a JSON object')
         
     | 
| 
      
 794 
     | 
    
         
            +
                    end
         
     | 
| 
      
 795 
     | 
    
         
            +
                    result
         
     | 
| 
      
 796 
     | 
    
         
            +
                  end.freeze
         
     | 
| 
       592 
797 
     | 
    
         
             
                end
         
     | 
| 
       593 
798 
     | 
    
         | 
| 
       594 
799 
     | 
    
         
             
                # schema resources which are ancestors of any subschemas below this schema.
         
     | 
| 
       595 
800 
     | 
    
         
             
                # this may include this schema if this is a schema resource root.
         
     | 
| 
       596 
     | 
    
         
            -
                # @private
         
     | 
| 
      
 801 
     | 
    
         
            +
                # @api private
         
     | 
| 
       597 
802 
     | 
    
         
             
                # @return [Array<JSI::Schema>]
         
     | 
| 
       598 
803 
     | 
    
         
             
                def jsi_subschema_resource_ancestors
         
     | 
| 
       599 
804 
     | 
    
         
             
                  if schema_resource_root?
         
     | 
| 
       600 
     | 
    
         
            -
                    jsi_schema_resource_ancestors 
     | 
| 
      
 805 
     | 
    
         
            +
                    jsi_schema_resource_ancestors.dup.push(self).freeze
         
     | 
| 
       601 
806 
     | 
    
         
             
                  else
         
     | 
| 
       602 
807 
     | 
    
         
             
                    jsi_schema_resource_ancestors
         
     | 
| 
       603 
808 
     | 
    
         
             
                  end
         
     | 
| 
       604 
809 
     | 
    
         
             
                end
         
     | 
| 
      
 810 
     | 
    
         
            +
             
     | 
| 
      
 811 
     | 
    
         
            +
                private
         
     | 
| 
      
 812 
     | 
    
         
            +
             
     | 
| 
      
 813 
     | 
    
         
            +
                def jsi_schema_initialize
         
     | 
| 
      
 814 
     | 
    
         
            +
                  @schema_ref_map = jsi_memomap(key_by: proc { |i| i[:keyword] }) do |keyword: , value: |
         
     | 
| 
      
 815 
     | 
    
         
            +
                    Schema::Ref.new(value, ref_schema: self)
         
     | 
| 
      
 816 
     | 
    
         
            +
                  end
         
     | 
| 
      
 817 
     | 
    
         
            +
                  @schema_uris_map = jsi_memomap(&method(:schema_uris_compute))
         
     | 
| 
      
 818 
     | 
    
         
            +
                  @subschema_map = jsi_memomap(&method(:subschema_compute))
         
     | 
| 
      
 819 
     | 
    
         
            +
                  @resource_root_subschema_map = jsi_memomap(&method(:resource_root_subschema_compute))
         
     | 
| 
      
 820 
     | 
    
         
            +
                  @described_object_property_names_map = jsi_memomap(&method(:described_object_property_names_compute))
         
     | 
| 
      
 821 
     | 
    
         
            +
                end
         
     | 
| 
       605 
822 
     | 
    
         
             
              end
         
     | 
| 
       606 
823 
     | 
    
         
             
            end
         
     |