Class: ElasticGraph::SchemaDefinition::API
- Inherits:
-
Object
- Object
- ElasticGraph::SchemaDefinition::API
- Defined in:
- lib/elastic_graph/schema_definition/api.rb
Overview
Root API object that provides the schema definition API.
Instance Attribute Summary collapse
-
#factory ⇒ Factory
readonly
Object responsible for instantiating all schema element classes.
-
#state ⇒ State
readonly
Object which holds all state for the schema definition.
Instance Method Summary collapse
-
#as_active_instance ⇒ Object
While the block executes, makes any ‘ElasticGraph.define_schema` calls operate on this `API` instance.
-
#deleted_type(name) ⇒ void
Registers the name of a type that existed in a prior version of the schema but has been deleted.
-
#enum_type(name) {|SchemaElements::EnumType| ... } ⇒ void
Defines a [GraphQL enum type](graphql.org/learn/schema/#enum-types).
-
#initialize(schema_elements, index_document_sizes, extension_modules: [], derived_type_name_formats: {}, type_name_overrides: {}, enum_value_overrides_by_type: {}, output: $stdout) ⇒ API
constructor
A new instance of API.
-
#interface_type(name) {|SchemaElements::InterfaceType| ... } ⇒ void
Defines a [GraphQL interface](graphql.org/learn/schema/#interface-types).
-
#json_schema_strictness(allow_omitted_fields: false, allow_extra_fields: true) ⇒ void
Defines strictness of the JSON schema validation.
-
#json_schema_version(version) ⇒ void
Defines the version number of the current JSON schema.
-
#object_type(name) {|SchemaElements::ObjectType| ... } ⇒ void
Defines a [GraphQL object type](graphql.org/learn/schema/#object-types-and-fields) Use it to define a concrete type that has subfields.
-
#on_built_in_types {|SchemaElements::EnumType, SchemaElements::InputType, SchemaElements::InterfaceType, SchemaElements::ObjectType, SchemaElements::ScalarType, SchemaElements::UnionType| ... } ⇒ void
Registers a customization callback that will be applied to every built-in type automatically provided by ElasticGraph.
-
#on_root_query_type {|SchemaElements::ObjectType| ... } ⇒ void
Registers a customization callback that will be applied to the root ‘Query` type when it is generated.
-
#raw_sdl(string) ⇒ void
Defines a raw GraphQL SDL snippet that will be included in the generated ‘schema.graphql` artifact.
-
#register_graphql_extension(extension_module, defined_at:, **config) ⇒ void
Registers a GraphQL extension module that will be loaded and used by ‘elasticgraph-graphql`.
-
#register_graphql_resolver(name, klass, defined_at:, built_in: false, **resolver_config) ⇒ void
Registers a GraphQL resolver that will be loaded and used by ‘elasticgraph-graphql`.
-
#results ⇒ Object
The results of the schema definition.
-
#scalar_type(name) {|SchemaElements::ScalarType| ... } ⇒ void
Defines a [GraphQL scalar type](graphql.org/learn/schema/#scalar-types).
-
#union_type(name) {|SchemaElements::UnionType| ... } ⇒ void
Defines a [GraphQL union type](graphql.org/learn/schema/#union-types).
Constructor Details
#initialize(schema_elements, index_document_sizes, extension_modules: [], derived_type_name_formats: {}, type_name_overrides: {}, enum_value_overrides_by_type: {}, output: $stdout) ⇒ API
Returns a new instance of API.
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
# File 'lib/elastic_graph/schema_definition/api.rb', line 59 def initialize( schema_elements, index_document_sizes, extension_modules: [], derived_type_name_formats: {}, type_name_overrides: {}, enum_value_overrides_by_type: {}, output: $stdout ) @state = State.with( api: self, schema_elements: schema_elements, index_document_sizes: index_document_sizes, derived_type_name_formats: derived_type_name_formats, type_name_overrides: type_name_overrides, enum_value_overrides_by_type: enum_value_overrides_by_type, output: output ) @factory = @state.factory extension_modules.each { |mod| extend(mod) } # These lines must come _after_ the extension modules are applied, so that the extension modules # have a chance to hook into the factory in order to customize built in types if desired. @factory.new_built_in_types(self).register_built_in_types @state.initially_registered_built_in_types.merge(@state.types_by_name.keys) end |
Instance Attribute Details
#factory ⇒ Factory (readonly)
Returns object responsible for instantiating all schema element classes.
56 57 58 |
# File 'lib/elastic_graph/schema_definition/api.rb', line 56 def factory @factory end |
#state ⇒ State (readonly)
Returns object which holds all state for the schema definition.
53 54 55 |
# File 'lib/elastic_graph/schema_definition/api.rb', line 53 def state @state end |
Instance Method Details
#as_active_instance ⇒ Object
While the block executes, makes any ‘ElasticGraph.define_schema` calls operate on this `API` instance.
513 514 515 516 517 518 519 520 |
# File 'lib/elastic_graph/schema_definition/api.rb', line 513 def as_active_instance # @type var old_value: API? old_value = ::Thread.current[:ElasticGraph_SchemaDefinition_API_instance] ::Thread.current[:ElasticGraph_SchemaDefinition_API_instance] = self yield ensure ::Thread.current[:ElasticGraph_SchemaDefinition_API_instance] = old_value end |
#deleted_type(name) ⇒ void
In situations where this API applies, ElasticGraph will give you an error message indicating that you need to use this API or SchemaElements::TypeWithSubfields#renamed_from. Likewise, when ElasticGraph no longer needs to know about this, it’ll give you a warning indicating the call to this method can be removed.
This method returns an undefined value.
Registers the name of a type that existed in a prior version of the schema but has been deleted.
274 275 276 277 278 279 280 281 |
# File 'lib/elastic_graph/schema_definition/api.rb', line 274 def deleted_type(name) @state.register_deleted_type( name, defined_at: caller_locations(1, 1).to_a.first, # : ::Thread::Backtrace::Location defined_via: %(schema.deleted_type "#{name}") ) nil end |
#enum_type(name) {|SchemaElements::EnumType| ... } ⇒ void
This method returns an undefined value.
Defines a [GraphQL enum type](graphql.org/learn/schema/#enum-types). The type is restricted to an enumerated set of values, each with a unique name. Use ‘value` or `values` to define the enum values in the passed block.
Note: if required by your configuration, this may generate a pair of Enum types (an input enum and an output enum).
202 203 204 205 |
# File 'lib/elastic_graph/schema_definition/api.rb', line 202 def enum_type(name, &block) @state.register_enum_type @factory.new_enum_type(name.to_s, &block) nil end |
#interface_type(name) {|SchemaElements::InterfaceType| ... } ⇒ void
An interface type can declare an index with Mixins::HasIndices#index. This creates a _mixed-type index_ in the datastore where concrete types that implement the interface coexist. A subtype may opt out of this shared index inheritance and use a dedicated index by declaring its own with Mixins::HasIndices#index.
This method returns an undefined value.
Defines a [GraphQL interface](graphql.org/learn/schema/#interface-types). Use it to define an abstract supertype with one or more fields that concrete implementations of the interface must also define. Each implementation can be an SchemaElements::ObjectType or SchemaElements::InterfaceType.
171 172 173 174 |
# File 'lib/elastic_graph/schema_definition/api.rb', line 171 def interface_type(name, &block) @state.register_object_interface_or_union_type @factory.new_interface_type(name.to_s, &block) nil end |
#json_schema_strictness(allow_omitted_fields: false, allow_extra_fields: true) ⇒ void
If you allow both omitted fields and extra fields, ElasticGraph’s JSON schema validation will allow (and ignore) misspelled field names in indexing events. For example, if the ElasticGraph schema has a nullable field named ‘parentId` but the publisher accidentally provides it as `parent_id`, ElasticGraph would happily ignore the `parent_id` field entirely, because `parentId` is allowed to be omitted and `parent_id` would be treated as an extra field. Therefore, we recommend that you only set one of these to `true` (or none).
This method returns an undefined value.
Defines strictness of the JSON schema validation. By default, the JSON schema will require all fields to be provided by the publisher (but they can be nullable) and will ignore extra fields that are not defined in the schema. Use this method to configure this behavior.
461 462 463 464 465 466 467 468 469 470 471 472 473 |
# File 'lib/elastic_graph/schema_definition/api.rb', line 461 def json_schema_strictness(allow_omitted_fields: false, allow_extra_fields: true) unless [true, false].include?(allow_omitted_fields) raise Errors::SchemaError, "`allow_omitted_fields` must be true or false" end unless [true, false].include?(allow_extra_fields) raise Errors::SchemaError, "`allow_extra_fields` must be true or false" end @state.allow_omitted_json_schema_fields = allow_omitted_fields @state.allow_extra_json_schema_fields = allow_extra_fields nil end |
#json_schema_version(version) ⇒ void
While this is an important part of how ElasticGraph is designed to support schema evolution, it can be annoying constantly have to increment this while rapidly changing the schema during prototyping. You can disable the requirement to increment this on every JSON schema change by setting ‘enforce_json_schema_version` to `false` in your `Rakefile`.
This method returns an undefined value.
Defines the version number of the current JSON schema. Importantly, every time a change is made that impacts the JSON schema artifact, the version number must be incremented to ensure that each different version of the JSON schema is identified by a unique version number. The publisher will then include this version number in published events to identify the version of the schema it was using. This avoids the need to deploy the publisher and ElasticGraph indexer at the same time to keep them in sync.
429 430 431 432 433 434 435 436 437 438 439 440 441 |
# File 'lib/elastic_graph/schema_definition/api.rb', line 429 def json_schema_version(version) if !version.is_a?(Integer) || version < 1 raise Errors::SchemaError, "`json_schema_version` must be a positive integer. Specified version: #{version}" end if @state.json_schema_version raise Errors::SchemaError, "`json_schema_version` can only be set once on a schema. Previously-set version: #{@state.json_schema_version}" end @state.json_schema_version = version @state.json_schema_version_setter_location = caller_locations(1, 1).to_a.first nil end |
#object_type(name) {|SchemaElements::ObjectType| ... } ⇒ void
This method returns an undefined value.
Defines a [GraphQL object type](graphql.org/learn/schema/#object-types-and-fields) Use it to define a concrete type that has subfields. Object types can either be indexed (e.g. directly indexed in the datastore, and available to query from the root ‘Query` object) or embedded in other indexed types.
133 134 135 136 |
# File 'lib/elastic_graph/schema_definition/api.rb', line 133 def object_type(name, &block) @state.register_object_interface_or_union_type @factory.new_object_type(name.to_s, &block) nil end |
#on_built_in_types {|SchemaElements::EnumType, SchemaElements::InputType, SchemaElements::InterfaceType, SchemaElements::ObjectType, SchemaElements::ScalarType, SchemaElements::UnionType| ... } ⇒ void
This method returns an undefined value.
Registers a customization callback that will be applied to every built-in type automatically provided by ElasticGraph. Provides an opportunity to customize the built-in types (e.g. to add directives to them or whatever).
487 488 489 490 |
# File 'lib/elastic_graph/schema_definition/api.rb', line 487 def on_built_in_types(&customization_block) @state.built_in_types_customization_blocks << customization_block nil end |
#on_root_query_type {|SchemaElements::ObjectType| ... } ⇒ void
This method returns an undefined value.
Registers a customization callback that will be applied to the root ‘Query` type when it is generated.
503 504 505 506 507 508 |
# File 'lib/elastic_graph/schema_definition/api.rb', line 503 def on_root_query_type(&customization_block) on_built_in_types do |type| customization_block.call(_ = type) if type.name == "Query" end nil end |
#raw_sdl(string) ⇒ void
This method returns an undefined value.
Defines a raw GraphQL SDL snippet that will be included in the generated ‘schema.graphql` artifact. Designed to be an escape hatch, for when ElasticGraph doesn’t provide another way to write some type of GraphQL SDL element that you need. Currently, the only known use case is to define custom GraphQL directives.
104 105 106 107 |
# File 'lib/elastic_graph/schema_definition/api.rb', line 104 def raw_sdl(string) @state.sdl_parts << string nil end |
#register_graphql_extension(extension_module, defined_at:, **config) ⇒ void
This method returns an undefined value.
Registers a GraphQL extension module that will be loaded and used by ‘elasticgraph-graphql`. While such extension modules can also be configured in a settings YAML file, it can be useful to register it here when you want to ensure that the extension is used in all environments. For example, an extension library that defines custom schema elements (such as `elasticgraph-apollo`) may need to ensure its corresponding GraphQL extension module is used since the custom schema elements would not work correctly otherwise.
301 302 303 304 305 |
# File 'lib/elastic_graph/schema_definition/api.rb', line 301 def register_graphql_extension(extension_module, defined_at:, **config) extension = SchemaArtifacts::RuntimeMetadata::Extension.new(extension_module, defined_at, config) @state.graphql_extension_modules << SchemaArtifacts::RuntimeMetadata::GraphQLExtension.new(extension.to_dumpable_hash) nil end |
#register_graphql_resolver(name, klass, defined_at:, built_in: false, **resolver_config) ⇒ void
This method returns an undefined value.
Registers a GraphQL resolver that will be loaded and used by ‘elasticgraph-graphql`. To use a GraphQL resolver you have registered, set a field’s ‘resolver` to the name you provide when registering your resolver.
382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 |
# File 'lib/elastic_graph/schema_definition/api.rb', line 382 def register_graphql_resolver(name, klass, defined_at:, built_in: false, **resolver_config) extension = SchemaArtifacts::RuntimeMetadata::Extension.new(klass, defined_at, resolver_config) needs_lookahead = if extension.verify_against(SchemaArtifacts::RuntimeMetadata::GraphQLResolver::InterfaceWithLookahead).empty? true else extension.verify_against!(SchemaArtifacts::RuntimeMetadata::GraphQLResolver::InterfaceWithoutLookahead) false end resolver = SchemaArtifacts::RuntimeMetadata::GraphQLResolver.new( needs_lookahead: needs_lookahead, resolver_ref: extension.to_dumpable_hash ) @state.graphql_resolvers_by_name[name] = resolver if built_in @state.built_in_graphql_resolvers << name else @state.built_in_graphql_resolvers.delete(name) end nil end |
#results ⇒ Object
Returns the results of the schema definition.
408 409 410 |
# File 'lib/elastic_graph/schema_definition/api.rb', line 408 def results @results ||= @factory.new_results end |
#scalar_type(name) {|SchemaElements::ScalarType| ... } ⇒ void
This method returns an undefined value.
Defines a [GraphQL scalar type](graphql.org/learn/schema/#scalar-types). ElasticGraph itself uses this to define a few common scalar types (e.g. ‘Date` and `DateTime`), but it is also available to you to use to define your own custom scalar types.
256 257 258 259 |
# File 'lib/elastic_graph/schema_definition/api.rb', line 256 def scalar_type(name, &block) @state.register_scalar_type @factory.new_scalar_type(name.to_s, &block) nil end |
#union_type(name) {|SchemaElements::UnionType| ... } ⇒ void
A union type can declare an index with Mixins::HasIndices#index. This creates a _mixed-type index_ in the datastore where the union members coexist. A subtype may opt out of this shared index inheritance and use a dedicated index by declaring its own with Mixins::HasIndices#index.
This method returns an undefined value.
Defines a [GraphQL union type](graphql.org/learn/schema/#union-types). Use it to define an abstract supertype with one or more concrete subtypes. Each subtype must be an SchemaElements::ObjectType, but they do not have to share any fields in common.
237 238 239 240 |
# File 'lib/elastic_graph/schema_definition/api.rb', line 237 def union_type(name, &block) @state.register_object_interface_or_union_type @factory.new_union_type(name.to_s, &block) nil end |