Module: JSI

Includes:
Error
Defined in:
lib/jsi/ptr.rb,
lib/jsi/ref.rb,
lib/jsi/set.rb,
lib/jsi/uri.rb,
lib/jsi/base.rb,
lib/jsi/util.rb,
lib/jsi/schema.rb,
lib/jsi/struct.rb,
lib/jsi/version.rb,
lib/jsi/registry.rb,
lib/jsi/base/node.rb,
lib/jsi/jsi_coder.rb,
lib/jsi/schema/cxt.rb,
lib/jsi/schema_set.rb,
lib/jsi/validation.rb,
lib/jsi/simple_wrap.rb,
lib/jsi/schema/issue.rb,
lib/jsi/util/private.rb,
lib/jsi/util/typelike.rb,
lib/jsi/schema/dialect.rb,
lib/jsi/schema/draft04.rb,
lib/jsi/schema/draft06.rb,
lib/jsi/schema/draft07.rb,
lib/jsi/schema/element.rb,
lib/jsi/schema_classes.rb,
lib/jsi/base/mutability.rb,
lib/jsi/metaschema_node.rb,
lib/jsi/schema/elements.rb,
lib/jsi/validation/error.rb,
lib/jsi/schema/vocabulary.rb,
lib/jsi/validation/result.rb,
lib/jsi/schema/draft202012.rb,
lib/jsi/schema/elements/id.rb,
lib/jsi/schema/elements/not.rb,
lib/jsi/schema/elements/ref.rb,
lib/jsi/schema/elements/enum.rb,
lib/jsi/schema/elements/self.rb,
lib/jsi/schema/elements/type.rb,
lib/jsi/schema/elements/const.rb,
lib/jsi/schema/elements/items.rb,
lib/jsi/util/private/memo_map.rb,
lib/jsi/schema/elements/anchor.rb,
lib/jsi/schema/elements/format.rb,
lib/jsi/schema/elements/comment.rb,
lib/jsi/schema/elements/default.rb,
lib/jsi/schema/elements/numeric.rb,
lib/jsi/schema/elements/pattern.rb,
lib/jsi/schema/elements/some_of.rb,
lib/jsi/schema/elements/xschema.rb,
lib/jsi/schema/elements/contains.rb,
lib/jsi/schema/elements/examples.rb,
lib/jsi/schema/elements/required.rb,
lib/jsi/schema/dynamic_anchor_map.rb,
lib/jsi/schema/elements/info_bool.rb,
lib/jsi/schema/elements/properties.rb,
lib/jsi/schema/elements/definitions.rb,
lib/jsi/schema/elements/dynamic_ref.rb,
lib/jsi/schema/elements/info_string.rb,
lib/jsi/schema/elements/xvocabulary.rb,
lib/jsi/schema/schema_ancestor_node.rb,
lib/jsi/schema/cxt/child_application.rb,
lib/jsi/schema/elements/dependencies.rb,
lib/jsi/schema/elements/if_then_else.rb,
lib/jsi/schema/cxt/inplace_application.rb,
lib/jsi/schema/elements/content_schema.rb,
lib/jsi/schema/elements/items_prefixed.rb,
lib/jsi/schema/elements/property_names.rb,
lib/jsi/schema/elements/contains_minmax.rb,
lib/jsi/schema/elements/numeric_draft04.rb,
lib/jsi/metaschema_node/bootstrap_schema.rb,
lib/jsi/schema/elements/array_validation.rb,
lib/jsi/schema/elements/content_encoding.rb,
lib/jsi/schema/elements/dependent_schemas.rb,
lib/jsi/schema/elements/object_validation.rb,
lib/jsi/schema/elements/string_validation.rb,
lib/jsi/schema/elements/unevaluated_items.rb,
lib/jsi/schema/elements/content_media_type.rb,
lib/jsi/schema/elements/dependent_required.rb,
lib/schemas/json-schema.org/draft-04/schema.rb,
lib/schemas/json-schema.org/draft-06/schema.rb,
lib/schemas/json-schema.org/draft-07/schema.rb,
lib/jsi/schema/elements/unevaluated_properties.rb,
lib/schemas/json-schema.org/draft/2020-12/schema.rb,
lib/jsi.rb

Defined Under Namespace

Modules: Error, JSONSchemaDraft04, JSONSchemaDraft06, JSONSchemaDraft07, JSONSchemaDraft202012, Schema, SimpleWrap, Util, Validation Classes: Base, JSICoder, MetaSchemaNode, Ptr, Ref, Registry, SchemaModule, SchemaSet

Constant Summary collapse

VERSION =
"0.0.9".freeze
SchemaRegistry =
Deprecated.

after v0.8

Registry
DEFAULT_CONTENT_TO_IMMUTABLE =
proc do |content|
  Util.deep_to_frozen(content, not_implemented: proc do |instance|
    raise(ArgumentError, [
      "JSI does not know how to make the given instance immutable.",
      "See new_jsi / new_schema `mutable` param and `to_immutable` configuration documentation for options.",
      "https://www.rubydoc.info/gems/jsi/#{VERSION}/JSI/SchemaSet#new_jsi-instance_method",
      "Given instance: #{instance.pretty_inspect.chomp}",
    ].join("\n"))
  end)
end
DEFAULT_REGISTRY =
Registry.new.tap do |registry|
  registry.autoload_uri("http://json-schema.org/draft-04/schema") { JSI::JSONSchemaDraft04.schema }
  registry.autoload_uri("http://json-schema.org/draft-06/schema") { JSI::JSONSchemaDraft06.schema }
  registry.autoload_uri("http://json-schema.org/draft-07/schema") { JSI::JSONSchemaDraft07.schema }
  registry.autoload_uri("https://json-schema.org/draft/2020-12/schema") { JSI::JSONSchemaDraft202012.schema }
  registry.autoload_uri("https://json-schema.org/draft/2020-12/meta/core")         { JSI::JSONSchemaDraft202012::Core.schema }
  registry.autoload_uri("https://json-schema.org/draft/2020-12/meta/applicator")    { JSI::JSONSchemaDraft202012::Applicator.schema }
  registry.autoload_uri("https://json-schema.org/draft/2020-12/meta/unevaluated")    { JSI::JSONSchemaDraft202012::Unevaluated.schema }
  registry.autoload_uri("https://json-schema.org/draft/2020-12/meta/validation")      { JSI::JSONSchemaDraft202012::Validation.schema }
  registry.autoload_uri("https://json-schema.org/draft/2020-12/meta/meta-data")        { JSI::JSONSchemaDraft202012::MetaData.schema }
  registry.autoload_uri("https://json-schema.org/draft/2020-12/meta/format-annotation") { JSI::JSONSchemaDraft202012::FormatAnnotation.schema }
  registry.autoload_uri("https://json-schema.org/draft/2020-12/meta/content")          { JSI::JSONSchemaDraft202012::Content.schema }
  registry.autoload_vocabulary_uri("https://json-schema.org/draft/2020-12/vocab/core")            { JSI::Schema::Draft202012::Vocab::CORE }
  registry.autoload_vocabulary_uri("https://json-schema.org/draft/2020-12/vocab/unevaluated")      { JSI::Schema::Draft202012::Vocab::UNEVALUATED }
  registry.autoload_vocabulary_uri("https://json-schema.org/draft/2020-12/vocab/format-annotation") { JSI::Schema::Draft202012::Vocab::FORMAT_ANNOTATION }
  registry.autoload_vocabulary_uri("https://json-schema.org/draft/2020-12/vocab/validation")       { JSI::Schema::Draft202012::Vocab::VALIDATION }
  registry.autoload_vocabulary_uri("https://json-schema.org/draft/2020-12/vocab/content")         { JSI::Schema::Draft202012::Vocab::CONTENT }
  registry.autoload_vocabulary_uri("https://json-schema.org/draft/2020-12/vocab/applicator")     { JSI::Schema::Draft202012::Vocab::APPLICATOR }
  registry.autoload_vocabulary_uri("https://json-schema.org/draft/2020-12/vocab/meta-data")     { JSI::Schema::Draft202012::Vocab::METADATA }
  registry.autoload_dialect_uri("http://json-schema.org/draft-04/schema") { Schema::Draft04::DIALECT }
  registry.autoload_dialect_uri("http://json-schema.org/draft-06/schema") { Schema::Draft06::DIALECT }
  registry.autoload_dialect_uri("http://json-schema.org/draft-07/schema") { Schema::Draft07::DIALECT }
  registry.autoload_dialect_uri("https://json-schema.org/draft/2020-12/schema") { Schema::Draft202012::DIALECT }
end.freeze
DEFAULT_TRANSLATOR =
proc { |_key, default: , **_| default }

Class Method Summary collapse

Class Method Details

.default_metaschemanil, Base + Schema + Schema::MetaSchema

An application-wide default meta-schema set by default_metaschema=, used by new_schema to instantiate schemas that do not specify their meta-schema using a $schema property.

Returns:



156
157
158
# File 'lib/jsi/schema.rb', line 156

def default_metaschema
  @default_metaschema
end

.default_metaschema=(default_metaschema) ⇒ Object

Sets default_metaschema to a schema indicated by the given param.

Parameters:

  • default_metaschema (Schema::MetaSchema, SchemaModule::MetaSchemaModule, #to_str, nil)

    Indicates the default meta-schema. This may be a meta-schema or a meta-schema's schema module (e.g. JSI::JSONSchemaDraft07), or a URI (as would be in a $schema keyword).

    nil to unset.



168
169
170
# File 'lib/jsi/schema.rb', line 168

def default_metaschema=(default_metaschema)
  @default_metaschema = default_metaschema.nil? ? nil : Schema.ensure_metaschema(default_metaschema)
end

.new_metaschema_node(metaschema_document, schema_documents: nil, **conf_kw) ⇒ MetaSchemaNode

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Instantiates the given metaschema_document as a MetaSchemaNode.

Parameters:

Returns:

Raises:



127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
# File 'lib/jsi.rb', line 127

def self.new_metaschema_node(metaschema_document,
    schema_documents: nil,
    **conf_kw
)
  raise(BlockGivenError) if block_given?

  conf = MetaSchemaNode::Conf.new(**conf_kw)

  # need the metaschema_document root to be registered in the bootstrap_registry if...
  register_bootstrap_metaschema =
    # the root is a schema
    conf.root_schema_ref == conf.metaschema_root_ref &&
    # and the metaschema ref is not fragment-only
    !conf.metaschema_root_ref.merge(fragment: nil).empty? &&
    # and it's not already registered (I don't know that an externally supplied bootstrap_registry
    # would ever need to register the meta-schema differently than this does, but allow for it)
    (!conf.bootstrap_registry || !conf.bootstrap_registry.registered?(conf.metaschema_root_ref.merge(fragment: nil)))

  if !conf.bootstrap_registry && (register_bootstrap_metaschema || schema_documents)
    conf = conf.merge(bootstrap_registry: Registry.new)
  end
  if !conf.registry && (register_bootstrap_metaschema || schema_documents)
    conf = conf.merge(registry: Registry.new)
  end

  metaschema_document = conf.to_immutable.call(metaschema_document) if conf.to_immutable
  schema_documents = schema_documents.map(&conf.to_immutable) if schema_documents && conf.to_immutable

  to_register = []
  to_register.concat(schema_documents) if schema_documents
  to_register.push(metaschema_document) if register_bootstrap_metaschema
  to_register.each do |document|
    conf.bootstrap_registry.register_immediate(conf.dialect.bootstrap_schema(
      jsi_document: document,
      jsi_registry: conf.bootstrap_registry,
    ))
  end

  MetaSchemaNode.new(
    jsi_document: metaschema_document,
    jsi_conf: conf,
  ).jsi_initialize_finish
end

.new_schema(schema_content, default_metaschema: nil, base_uri: nil, register: true, stringify_symbol_keys: true, **conf_kw) ⇒ Base + Schema

Instantiates the given schema content as a JSI Schema.

The meta-schema that describes the schema must be indicated:

  • If the schema object has a $schema property, that URI is resolved using the configured registry (by default JSI.registry), and that meta-schema is used. For example:
  JSI.new_schema({
    "$schema" => "http://json-schema.org/draft-07/schema#",
    "properties" => ...,
  })
  • if no $schema property is present, the default_metaschema param is used, if the caller specifies it. For example:
  JSI.new_schema({"properties" => ...}, default_metaschema: JSI::JSONSchemaDraft07)
  • if no default_metaschema param is specified, the application-wide default JSI.default_metaschema is used, if the application has set it. For example:
  JSI.default_metaschema = JSI::JSONSchemaDraft07
  JSI.new_schema({"properties" => ...})

An ArgumentError is raised if none of these indicates a meta-schema to use.

Note that if you are instantiating a schema known to have no $schema property, an alternative to specifying a default_metaschema is to call new_schema on the meta-schema or its schema module, e.g. JSI::JSONSchemaDraft07.new_schema(my_schema_content). This will ignore any $schema keyword that may be present.

Schemas instantiated with new_schema are immutable, their content transformed using the configured to_immutable.

Most parameters are passed to JSI::SchemaSet#new_jsi and are documented there, but some have different defaults for JSI.new_schema.

Parameters:

  • default_metaschema (Schema::MetaSchema, SchemaModule::MetaSchemaModule, #to_str) (defaults to: nil)

    Indicates the meta-schema to use if the given schema_content does not have a $schema property. This may be a meta-schema or a meta-schema's schema module (e.g. JSI::JSONSchemaDraft07), or a URI (as would be in a $schema keyword).

  • base_uri (defaults to: nil)
  • register (defaults to: true)
  • stringify_symbol_keys (defaults to: true)
  • schema_content

    an object to be instantiated as a JSI Schema - typically a Hash

  • conf_kw

    Additional keyword params are passed to initialize a JSI::Base::Conf, the JSI's JSI::Base#jsi_conf.

Returns:

  • (Base + Schema)

    A JSI which is a Schema whose content comes from the given schema_content and whose schemas are in-place applicators of the indicated meta-schema.

Raises:



229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
# File 'lib/jsi/schema.rb', line 229

def new_schema(schema_content,
    default_metaschema: nil,
    base_uri: nil,
    register: true,
    stringify_symbol_keys: true,
    **conf_kw
)
  raise(BlockGivenError) if block_given?
  new_schema_params = {
    base_uri: base_uri,
    register: register,
    stringify_symbol_keys: stringify_symbol_keys,
    **conf_kw,
  }
  conf = Base::Conf.new(**conf_kw) # some redundancy instantiating this - not passed to MetaSchema#new_schema, just used in this method
  default_metaschema_new_schema = -> {
    default_metaschema = if default_metaschema
      Schema.ensure_metaschema(default_metaschema, name: "default_metaschema", registry: conf.registry)
    elsif self.default_metaschema
      self.default_metaschema
    else
      raise(ArgumentError, [
        "When instantiating a schema with no `$schema` property, you must specify its meta-schema by one of these methods:",
        "- pass the `default_metaschema` param to this method",
        "  e.g.: JSI.new_schema(..., default_metaschema: JSI::JSONSchemaDraft07)",
        "- invoke `new_schema` on the appropriate meta-schema or its schema module",
        "  e.g.: JSI::JSONSchemaDraft07.new_schema(...)",
        "- set JSI.default_metaschema to an application-wide default meta-schema initially",
        "  e.g.: JSI.default_metaschema = JSI::JSONSchemaDraft07",
        "instantiating schema_content: #{schema_content.pretty_inspect.chomp}",
      ].join("\n"))
    end
    default_metaschema.new_schema(schema_content, **new_schema_params)
  }
  if schema_content.is_a?(Schema)
    raise(TypeError, [
      "Given schema_content is already a JSI::Schema. It cannot be instantiated as the content of a schema.",
      "given: #{schema_content.pretty_inspect.chomp}",
    ].join("\n"))
  elsif schema_content.is_a?(JSI::Base)
    raise(TypeError, [
      "Given schema_content is a JSI::Base. It cannot be instantiated as the content of a schema.",
      "given: #{schema_content.pretty_inspect.chomp}",
    ].join("\n"))
  elsif schema_content.respond_to?(:to_hash)
    id = schema_content['$schema'] || stringify_symbol_keys && schema_content[:'$schema']
    if id
      unless id.respond_to?(:to_str)
        raise(ArgumentError, "given schema_content keyword `$schema` is not a string")
      end
      metaschema = Schema.ensure_metaschema(id, name: '$schema', registry: conf.registry)
      metaschema.new_schema(schema_content, **new_schema_params)
    else
      default_metaschema_new_schema.call
    end
  else
    default_metaschema_new_schema.call
  end
end

.new_schema_module(schema_content, **kw) { ... } ⇒ JSI::SchemaModule

Instantiates the given schema content as a JSI Schema, passing all params to new_schema, and returns its JSI Schema Module.

Yields:

  • If a block is given, it is evaluated in the context of the schema module using Module#module_exec.

Returns:



115
116
117
118
119
# File 'lib/jsi.rb', line 115

def self.new_schema_module(schema_content, **kw, &block)
  schema_jsi = new_schema(schema_content, **kw)
  schema_jsi.jsi_schema_module_exec(&block) if block
  schema_jsi.jsi_schema_module
end

.registryRegistry

JSI.registry is the default Registry in which schemas are registered and from which they resolve references.

Returns:



175
176
177
# File 'lib/jsi.rb', line 175

def self.registry
  @registry
end

.registry=(registry) ⇒ Object

Parameters:



185
186
187
# File 'lib/jsi.rb', line 185

def self.registry=(registry)
  @registry = registry
end

.schema_registryObject

Deprecated.

after v0.8



180
181
182
# File 'lib/jsi.rb', line 180

def self.schema_registry
  @registry
end

.t(key, default:, **options) ⇒ String

translation

Parameters:

  • key (String)
  • default (String)

Returns:

  • (String)


220
221
222
# File 'lib/jsi.rb', line 220

def self.t(key, default: , **options)
  translator.call(key, default: default, **options)
end

.translator#call

Returns:

  • (#call)


225
226
227
# File 'lib/jsi.rb', line 225

def self.translator
  @translator
end

.translator=(translator) ⇒ Object

e.g. JSI.translator = I18n.method(:translate)

Parameters:

  • translator (#call)


231
232
233
# File 'lib/jsi.rb', line 231

def self.translator=(translator)
  @translator = translator
end