elasticgraph-schema_definition 1.0.1 → 1.0.3.rc1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +1 -1
  3. data/lib/elastic_graph/schema_definition/api.rb +34 -2
  4. data/lib/elastic_graph/schema_definition/factory.rb +31 -1
  5. data/lib/elastic_graph/schema_definition/indexing/derived_fields/append_only_set.rb +1 -1
  6. data/lib/elastic_graph/schema_definition/indexing/derived_fields/field_initializer_support.rb +1 -1
  7. data/lib/elastic_graph/schema_definition/indexing/derived_fields/immutable_value.rb +1 -1
  8. data/lib/elastic_graph/schema_definition/indexing/derived_fields/min_or_max_value.rb +1 -1
  9. data/lib/elastic_graph/schema_definition/indexing/derived_indexed_type.rb +1 -1
  10. data/lib/elastic_graph/schema_definition/indexing/event_envelope.rb +1 -1
  11. data/lib/elastic_graph/schema_definition/indexing/field.rb +8 -2
  12. data/lib/elastic_graph/schema_definition/indexing/field_reference.rb +6 -4
  13. data/lib/elastic_graph/schema_definition/indexing/field_type/enum.rb +1 -1
  14. data/lib/elastic_graph/schema_definition/indexing/field_type/object.rb +10 -4
  15. data/lib/elastic_graph/schema_definition/indexing/field_type/scalar.rb +1 -1
  16. data/lib/elastic_graph/schema_definition/indexing/field_type/union.rb +1 -1
  17. data/lib/elastic_graph/schema_definition/indexing/index.rb +39 -4
  18. data/lib/elastic_graph/schema_definition/indexing/json_schema_field_metadata.rb +1 -1
  19. data/lib/elastic_graph/schema_definition/indexing/json_schema_with_metadata.rb +4 -4
  20. data/lib/elastic_graph/schema_definition/indexing/list_counts_mapping.rb +1 -1
  21. data/lib/elastic_graph/schema_definition/indexing/relationship_resolver.rb +1 -1
  22. data/lib/elastic_graph/schema_definition/indexing/rollover_config.rb +1 -1
  23. data/lib/elastic_graph/schema_definition/indexing/update_target_factory.rb +1 -1
  24. data/lib/elastic_graph/schema_definition/indexing/update_target_resolver.rb +3 -4
  25. data/lib/elastic_graph/schema_definition/json_schema_pruner.rb +1 -1
  26. data/lib/elastic_graph/schema_definition/mixins/can_be_graphql_only.rb +1 -1
  27. data/lib/elastic_graph/schema_definition/mixins/has_derived_graphql_type_customizations.rb +1 -1
  28. data/lib/elastic_graph/schema_definition/mixins/has_directives.rb +1 -1
  29. data/lib/elastic_graph/schema_definition/mixins/has_documentation.rb +1 -1
  30. data/lib/elastic_graph/schema_definition/mixins/has_indices.rb +20 -14
  31. data/lib/elastic_graph/schema_definition/mixins/has_readable_to_s_and_inspect.rb +1 -1
  32. data/lib/elastic_graph/schema_definition/mixins/has_subtypes.rb +1 -1
  33. data/lib/elastic_graph/schema_definition/mixins/has_type_info.rb +1 -1
  34. data/lib/elastic_graph/schema_definition/mixins/implements_interfaces.rb +1 -1
  35. data/lib/elastic_graph/schema_definition/mixins/supports_default_value.rb +1 -1
  36. data/lib/elastic_graph/schema_definition/mixins/supports_filtering_and_aggregation.rb +1 -1
  37. data/lib/elastic_graph/schema_definition/mixins/verifies_graphql_name.rb +1 -1
  38. data/lib/elastic_graph/schema_definition/rake_tasks.rb +6 -6
  39. data/lib/elastic_graph/schema_definition/results.rb +16 -5
  40. data/lib/elastic_graph/schema_definition/schema_artifact_manager.rb +39 -29
  41. data/lib/elastic_graph/schema_definition/schema_elements/argument.rb +1 -1
  42. data/lib/elastic_graph/schema_definition/schema_elements/built_in_types.rb +53 -1
  43. data/lib/elastic_graph/schema_definition/schema_elements/deprecated_element.rb +1 -1
  44. data/lib/elastic_graph/schema_definition/schema_elements/directive.rb +1 -1
  45. data/lib/elastic_graph/schema_definition/schema_elements/enum_type.rb +1 -1
  46. data/lib/elastic_graph/schema_definition/schema_elements/enum_value.rb +1 -1
  47. data/lib/elastic_graph/schema_definition/schema_elements/enum_value_namer.rb +1 -1
  48. data/lib/elastic_graph/schema_definition/schema_elements/enums_for_indexed_types.rb +1 -1
  49. data/lib/elastic_graph/schema_definition/schema_elements/field.rb +7 -4
  50. data/lib/elastic_graph/schema_definition/schema_elements/field_path.rb +1 -1
  51. data/lib/elastic_graph/schema_definition/schema_elements/field_source.rb +1 -1
  52. data/lib/elastic_graph/schema_definition/schema_elements/graphql_sdl_enumerator.rb +2 -1
  53. data/lib/elastic_graph/schema_definition/schema_elements/input_field.rb +1 -1
  54. data/lib/elastic_graph/schema_definition/schema_elements/input_type.rb +1 -1
  55. data/lib/elastic_graph/schema_definition/schema_elements/interface_type.rb +1 -1
  56. data/lib/elastic_graph/schema_definition/schema_elements/list_counts_state.rb +1 -1
  57. data/lib/elastic_graph/schema_definition/schema_elements/object_type.rb +1 -1
  58. data/lib/elastic_graph/schema_definition/schema_elements/relationship.rb +3 -2
  59. data/lib/elastic_graph/schema_definition/schema_elements/scalar_type.rb +82 -4
  60. data/lib/elastic_graph/schema_definition/schema_elements/sort_order_enum_value.rb +1 -1
  61. data/lib/elastic_graph/schema_definition/schema_elements/sub_aggregation_path.rb +1 -1
  62. data/lib/elastic_graph/schema_definition/schema_elements/type_namer.rb +1 -1
  63. data/lib/elastic_graph/schema_definition/schema_elements/type_reference.rb +2 -1
  64. data/lib/elastic_graph/schema_definition/schema_elements/type_with_subfields.rb +5 -3
  65. data/lib/elastic_graph/schema_definition/schema_elements/union_type.rb +1 -1
  66. data/lib/elastic_graph/schema_definition/scripting/file_system_repository.rb +1 -1
  67. data/lib/elastic_graph/schema_definition/scripting/script.rb +1 -1
  68. data/lib/elastic_graph/schema_definition/state.rb +7 -3
  69. data/lib/elastic_graph/schema_definition/test_support.rb +2 -3
  70. metadata +30 -24
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a17658df238a4aa9a7e736a04af8a2a5997785d4dc21a18424ed2f257082dfd5
4
- data.tar.gz: 2244f3f1fb2df109800b3a6952321a5b9ec472a010f7254e06ee40f23fdd49e0
3
+ metadata.gz: 9865f28d6f21c9522e9834f4bf583e563861fa6ee08f7a7c532588c6848853e0
4
+ data.tar.gz: d00543cabfa2cb9bbdbc225de3224cd16adee14fe50a559da63299deff50b658
5
5
  SHA512:
6
- metadata.gz: 44ba82a6ad8c34b8d1ec5fca695fb9a07a0f39f247352a4d6f83d9330af641c364ff89a566e2526868ff5a125637846ecc65a4de1ff431d0f33f0c2e0cd81810
7
- data.tar.gz: 544671f6f6e1d62fac830d5d343c9295993b3f93e42f803463c47ad143628c675fcf4f9786098c266639dd8a45cda77481d237e89d005f34ab4ee704bce45d39
6
+ metadata.gz: ffc146e35c36a4fe9010f16945ba8ecca2863cd22d0dd074d92f9b6abb428e1d318f10d1effce30506dc310714e12c34baa2420f36b2a499d28416db3742eca8
7
+ data.tar.gz: eefd1fa67fdf00e33eddb7b128953a0bf301d57894367be7b0dd525b67237e439ff239e40373e8a958d02dcc3b417c1a5f080ac72796146e1a0c29da136ad422
data/LICENSE.txt CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2024 - 2025 Block, Inc.
3
+ Copyright (c) 2024 - 2026 Block, Inc.
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
@@ -1,4 +1,4 @@
1
- # Copyright 2024 - 2025 Block, Inc.
1
+ # Copyright 2024 - 2026 Block, Inc.
2
2
  #
3
3
  # Use of this source code is governed by an MIT-style
4
4
  # license that can be found in the LICENSE file or at
@@ -387,7 +387,7 @@ module ElasticGraph
387
387
 
388
388
  # @return the results of the schema definition
389
389
  def results
390
- @results ||= Results.new(@state)
390
+ @results ||= @factory.new_results
391
391
  end
392
392
 
393
393
  # Defines the version number of the current JSON schema. Importantly, every time a change is made that impacts the JSON schema
@@ -421,6 +421,38 @@ module ElasticGraph
421
421
  nil
422
422
  end
423
423
 
424
+ # Defines strictness of the JSON schema validation. By default, the JSON schema will require all fields to be provided by the
425
+ # publisher (but they can be nullable) and will ignore extra fields that are not defined in the schema. Use this method to
426
+ # configure this behavior.
427
+ #
428
+ # @param allow_omitted_fields [bool] Whether nullable fields can be omitted from indexing events.
429
+ # @param allow_extra_fields [bool] Whether extra fields (e.g. beyond fields defined in the schema) can be included in indexing events.
430
+ # @return [void]
431
+ #
432
+ # @note If you allow both omitted fields and extra fields, ElasticGraph's JSON schema validation will allow (and ignore) misspelled
433
+ # field names in indexing events. For example, if the ElasticGraph schema has a nullable field named `parentId` but the publisher
434
+ # accidentally provides it as `parent_id`, ElasticGraph would happily ignore the `parent_id` field entirely, because `parentId`
435
+ # is allowed to be omitted and `parent_id` would be treated as an extra field. Therefore, we recommend that you only set one of
436
+ # these to `true` (or none).
437
+ #
438
+ # @example Allow omitted fields and disallow extra fields
439
+ # ElasticGraph.define_schema do |schema|
440
+ # schema.json_schema_strictness allow_omitted_fields: true, allow_extra_fields: false
441
+ # end
442
+ def json_schema_strictness(allow_omitted_fields: false, allow_extra_fields: true)
443
+ unless [true, false].include?(allow_omitted_fields)
444
+ raise Errors::SchemaError, "`allow_omitted_fields` must be true or false"
445
+ end
446
+
447
+ unless [true, false].include?(allow_extra_fields)
448
+ raise Errors::SchemaError, "`allow_extra_fields` must be true or false"
449
+ end
450
+
451
+ @state.allow_omitted_json_schema_fields = allow_omitted_fields
452
+ @state.allow_extra_json_schema_fields = allow_extra_fields
453
+ nil
454
+ end
455
+
424
456
  # Registers a customization callback that will be applied to every built-in type automatically provided by ElasticGraph. Provides
425
457
  # an opportunity to customize the built-in types (e.g. to add directives to them or whatever).
426
458
  #
@@ -1,4 +1,4 @@
1
- # Copyright 2024 - 2025 Block, Inc.
1
+ # Copyright 2024 - 2026 Block, Inc.
2
2
  #
3
3
  # Use of this source code is governed by an MIT-style
4
4
  # license that can be found in the LICENSE file or at
@@ -8,6 +8,9 @@
8
8
 
9
9
  require "elastic_graph/constants"
10
10
  require "elastic_graph/schema_definition/mixins/has_readable_to_s_and_inspect"
11
+ require "elastic_graph/schema_definition/results"
12
+ require "elastic_graph/schema_definition/indexing/index"
13
+ require "elastic_graph/schema_definition/schema_artifact_manager"
11
14
  require "elastic_graph/schema_definition/schema_elements/argument"
12
15
  require "elastic_graph/schema_definition/schema_elements/built_in_types"
13
16
  require "elastic_graph/schema_definition/schema_elements/deprecated_element"
@@ -275,6 +278,33 @@ module ElasticGraph
275
278
  end
276
279
  @@relationship_new = prevent_non_factory_instantiation_of(SchemaElements::Relationship)
277
280
 
281
+ def new_index(name, settings, type, &block)
282
+ @@index_new.call(name, settings, @state, type, &block)
283
+ end
284
+ @@index_new = prevent_non_factory_instantiation_of(Indexing::Index)
285
+
286
+ def new_results
287
+ @@results_new.call(@state)
288
+ end
289
+ @@results_new = prevent_non_factory_instantiation_of(Results)
290
+
291
+ def new_schema_artifact_manager(
292
+ schema_definition_results:,
293
+ schema_artifacts_directory:,
294
+ enforce_json_schema_version:,
295
+ output:,
296
+ max_diff_lines: 50
297
+ )
298
+ @@schema_artifact_manager_new.call(
299
+ schema_definition_results:,
300
+ schema_artifacts_directory:,
301
+ enforce_json_schema_version:,
302
+ output:,
303
+ max_diff_lines:
304
+ )
305
+ end
306
+ @@schema_artifact_manager_new = prevent_non_factory_instantiation_of(SchemaArtifactManager)
307
+
278
308
  # Responsible for creating a new `*AggregatedValues` type for an index leaf type.
279
309
  #
280
310
  # An index leaf type is a scalar, enum, object type that is backed by a single, indivisible
@@ -1,4 +1,4 @@
1
- # Copyright 2024 - 2025 Block, Inc.
1
+ # Copyright 2024 - 2026 Block, Inc.
2
2
  #
3
3
  # Use of this source code is governed by an MIT-style
4
4
  # license that can be found in the LICENSE file or at
@@ -1,4 +1,4 @@
1
- # Copyright 2024 - 2025 Block, Inc.
1
+ # Copyright 2024 - 2026 Block, Inc.
2
2
  #
3
3
  # Use of this source code is governed by an MIT-style
4
4
  # license that can be found in the LICENSE file or at
@@ -1,4 +1,4 @@
1
- # Copyright 2024 - 2025 Block, Inc.
1
+ # Copyright 2024 - 2026 Block, Inc.
2
2
  #
3
3
  # Use of this source code is governed by an MIT-style
4
4
  # license that can be found in the LICENSE file or at
@@ -1,4 +1,4 @@
1
- # Copyright 2024 - 2025 Block, Inc.
1
+ # Copyright 2024 - 2026 Block, Inc.
2
2
  #
3
3
  # Use of this source code is governed by an MIT-style
4
4
  # license that can be found in the LICENSE file or at
@@ -1,4 +1,4 @@
1
- # Copyright 2024 - 2025 Block, Inc.
1
+ # Copyright 2024 - 2026 Block, Inc.
2
2
  #
3
3
  # Use of this source code is governed by an MIT-style
4
4
  # license that can be found in the LICENSE file or at
@@ -1,4 +1,4 @@
1
- # Copyright 2024 - 2025 Block, Inc.
1
+ # Copyright 2024 - 2026 Block, Inc.
2
2
  #
3
3
  # Use of this source code is governed by an MIT-style
4
4
  # license that can be found in the LICENSE file or at
@@ -1,4 +1,4 @@
1
- # Copyright 2024 - 2025 Block, Inc.
1
+ # Copyright 2024 - 2026 Block, Inc.
2
2
  #
3
3
  # Use of this source code is governed by an MIT-style
4
4
  # license that can be found in the LICENSE file or at
@@ -28,7 +28,8 @@ module ElasticGraph
28
28
  :json_schema_customizations,
29
29
  :mapping_customizations,
30
30
  :source,
31
- :runtime_field_script
31
+ :runtime_field_script,
32
+ :doc_comment
32
33
  )
33
34
  # JSON schema overrides that automatically apply to specific mapping types so that the JSON schema
34
35
  # validation will reject values which cannot be indexed into fields of a specific mapping type.
@@ -70,6 +71,7 @@ module ElasticGraph
70
71
  .reverse # resolve layers from innermost to outermost wrappings
71
72
  .reduce(inner_json_schema) { |acc, layer| process_layer(layer, acc) }
72
73
  .merge(outer_json_schema_customizations)
74
+ .merge({"description" => doc_comment}.compact)
73
75
  .then { |h| Support::HashUtil.stringify_keys(h) }
74
76
  end
75
77
 
@@ -106,6 +108,10 @@ module ElasticGraph
106
108
  mapping_hash
107
109
  end
108
110
 
111
+ def nullable?
112
+ json_schema_layers.include?(:nullable)
113
+ end
114
+
109
115
  private
110
116
 
111
117
  def inner_json_schema
@@ -1,4 +1,4 @@
1
- # Copyright 2024 - 2025 Block, Inc.
1
+ # Copyright 2024 - 2026 Block, Inc.
2
2
  #
3
3
  # Use of this source code is governed by an MIT-style
4
4
  # license that can be found in the LICENSE file or at
@@ -18,7 +18,8 @@ module ElasticGraph
18
18
  :json_schema_options,
19
19
  :accuracy_confidence,
20
20
  :source,
21
- :runtime_field_script
21
+ :runtime_field_script,
22
+ :doc_comment
22
23
  )
23
24
 
24
25
  # A lazy reference to a {Field}. It contains all attributes needed to build a {Field}, but the referenced `type` may not be
@@ -40,11 +41,12 @@ module ElasticGraph
40
41
  json_schema_customizations: json_schema_options,
41
42
  mapping_customizations: mapping_options,
42
43
  source: source,
43
- runtime_field_script: runtime_field_script
44
+ runtime_field_script: runtime_field_script,
45
+ doc_comment: doc_comment
44
46
  )
45
47
  end
46
48
 
47
- # @dynamic initialize, with, name, name_in_index, type, mapping_options, json_schema_options, accuracy_confidence, source, runtime_field_script
49
+ # @dynamic initialize, with, name, name_in_index, type, mapping_options, json_schema_options, accuracy_confidence, source, runtime_field_script, doc_comment
48
50
  end
49
51
  end
50
52
  end
@@ -1,4 +1,4 @@
1
- # Copyright 2024 - 2025 Block, Inc.
1
+ # Copyright 2024 - 2026 Block, Inc.
2
2
  #
3
3
  # Use of this source code is governed by an MIT-style
4
4
  # license that can be found in the LICENSE file or at
@@ -1,4 +1,4 @@
1
- # Copyright 2024 - 2025 Block, Inc.
1
+ # Copyright 2024 - 2026 Block, Inc.
2
2
  #
3
3
  # Use of this source code is governed by an MIT-style
4
4
  # license that can be found in the LICENSE file or at
@@ -24,9 +24,11 @@ module ElasticGraph
24
24
  # @return [Hash<String, ::Object>] options to be included in the mapping
25
25
  # @!attribute [r] json_schema_options
26
26
  # @return [Hash<String, ::Object>] options to be included in the JSON schema
27
+ # @!attribute [r] doc_comment
28
+ # @return [String, nil] documentation for the type
27
29
  #
28
30
  # @api private
29
- class Object < Support::MemoizableData.define(:type_name, :subfields, :mapping_options, :json_schema_options)
31
+ class Object < Support::MemoizableData.define(:schema_def_state, :type_name, :subfields, :mapping_options, :json_schema_options, :doc_comment)
30
32
  # @return [Hash<String, ::Object>] the datastore mapping for this object type.
31
33
  def to_mapping
32
34
  @to_mapping ||= begin
@@ -48,6 +50,8 @@ module ElasticGraph
48
50
  other_source_subfields, json_schema_candidate_subfields = subfields.partition(&:source)
49
51
  validate_sourced_fields_have_no_json_schema_overrides(other_source_subfields)
50
52
  json_schema_subfields = json_schema_candidate_subfields.reject(&:runtime_field_script)
53
+ required_fields = json_schema_subfields
54
+ required_fields = required_fields.reject(&:nullable?) if schema_def_state.allow_omitted_json_schema_fields
51
55
 
52
56
  {
53
57
  "type" => "object",
@@ -55,8 +59,10 @@ module ElasticGraph
55
59
  # Note: `__typename` is intentionally not included in the `required` list. If `__typename` is present
56
60
  # we want it validated (as we do by merging in `json_schema_typename_field`) but we only want
57
61
  # to require it in the context of a union type. The union's json schema requires the field.
58
- "required" => json_schema_subfields.map(&:name).freeze
59
- }.freeze
62
+ "required" => required_fields.map(&:name).freeze,
63
+ "additionalProperties" => (false unless schema_def_state.allow_extra_json_schema_fields),
64
+ "description" => doc_comment
65
+ }.compact.freeze
60
66
  else
61
67
  Support::HashUtil.stringify_keys(json_schema_options)
62
68
  end
@@ -1,4 +1,4 @@
1
- # Copyright 2024 - 2025 Block, Inc.
1
+ # Copyright 2024 - 2026 Block, Inc.
2
2
  #
3
3
  # Use of this source code is governed by an MIT-style
4
4
  # license that can be found in the LICENSE file or at
@@ -1,4 +1,4 @@
1
- # Copyright 2024 - 2025 Block, Inc.
1
+ # Copyright 2024 - 2026 Block, Inc.
2
2
  #
3
3
  # Use of this source code is governed by an MIT-style
4
4
  # license that can be found in the LICENSE file or at
@@ -1,4 +1,4 @@
1
- # Copyright 2024 - 2025 Block, Inc.
1
+ # Copyright 2024 - 2026 Block, Inc.
2
2
  #
3
3
  # Use of this source code is governed by an MIT-style
4
4
  # license that can be found in the LICENSE file or at
@@ -36,7 +36,9 @@ module ElasticGraph
36
36
  # @return [Array<String>] path to the field used for shard routing
37
37
  # @!attribute [r] rollover_config
38
38
  # @return [RolloverConfig, nil] rollover configuration for the index
39
- class Index < Struct.new(:name, :default_sort_pairs, :settings, :schema_def_state, :indexed_type, :routing_field_path, :rollover_config)
39
+ # @!attribute [r] has_had_multiple_sources_flag
40
+ # @return [Boolean] whether this index has ever had multiple sources
41
+ class Index < Struct.new(:name, :default_sort_pairs, :settings, :schema_def_state, :indexed_type, :routing_field_path, :rollover_config, :has_had_multiple_sources_flag)
40
42
  include Mixins::HasReadableToSAndInspect.new { |i| i.name }
41
43
 
42
44
  # @param name [String] name of the index
@@ -53,7 +55,7 @@ module ElasticGraph
53
55
 
54
56
  settings = DEFAULT_SETTINGS.merge(Support::HashUtil.flatten_and_stringify_keys(settings, prefix: "index"))
55
57
 
56
- super(name, [], settings, schema_def_state, indexed_type, nil, nil)
58
+ super(name, [], settings, schema_def_state, indexed_type, nil, nil, false)
57
59
 
58
60
  schema_def_state.after_user_definition_complete do
59
61
  # `id` is the field Elasticsearch/OpenSearch use for routing by default:
@@ -188,6 +190,38 @@ module ElasticGraph
188
190
  end
189
191
  end
190
192
 
193
+ # Declares that this index has had (or currently has) multiple sources. This should be called when using
194
+ # `sourced_from` fields on an indexed type, as it indicates that the index may contain incomplete documents.
195
+ # Once set, this flag should remain set even if all `sourced_from` fields are later removed, because the index
196
+ # may still contain historical incomplete documents.
197
+ #
198
+ # @return [void]
199
+ #
200
+ # @example Declare that the index has had multiple sources
201
+ # ElasticGraph.define_schema do |schema|
202
+ # schema.object_type "Widget" do |t|
203
+ # t.field "id", "ID!"
204
+ # t.relates_to_one "owner", "Owner", via: "widget_ids", dir: :in
205
+ # t.field "owner_name", "String" do |f|
206
+ # f.sourced_from "owner", "name"
207
+ # end
208
+ #
209
+ # t.index "widgets" do |i|
210
+ # i.has_had_multiple_sources!
211
+ # end
212
+ # end
213
+ #
214
+ # schema.object_type "Owner" do |t|
215
+ # t.field "id", "ID!"
216
+ # t.field "name", "String"
217
+ # t.field "widget_ids", "[ID!]!"
218
+ # t.index "owners"
219
+ # end
220
+ # end
221
+ def has_had_multiple_sources!
222
+ self.has_had_multiple_sources_flag = true
223
+ end
224
+
191
225
  # @see #route_with
192
226
  # @return [Boolean] whether or not this index uses custom shard routing
193
227
  def uses_custom_routing?
@@ -227,7 +261,8 @@ module ElasticGraph
227
261
  field_path: public_field_path(graphql_field_path_name, explanation: "it is referenced as an index `default_sort` field").path_in_index,
228
262
  direction: direction
229
263
  )
230
- end
264
+ end,
265
+ has_had_multiple_sources: has_had_multiple_sources_flag
231
266
  )
232
267
  end
233
268
 
@@ -1,4 +1,4 @@
1
- # Copyright 2024 - 2025 Block, Inc.
1
+ # Copyright 2024 - 2026 Block, Inc.
2
2
  #
3
3
  # Use of this source code is governed by an MIT-style
4
4
  # license that can be found in the LICENSE file or at
@@ -1,4 +1,4 @@
1
- # Copyright 2024 - 2025 Block, Inc.
1
+ # Copyright 2024 - 2026 Block, Inc.
2
2
  #
3
3
  # Use of this source code is governed by an MIT-style
4
4
  # license that can be found in the LICENSE file or at
@@ -160,11 +160,11 @@ module ElasticGraph
160
160
  type.indexed? && !@derived_indexing_type_names.include?(type.name)
161
161
  end
162
162
 
163
- types_to_check.flat_map do |object_type|
164
- object_type.indices.flat_map do |index_def|
163
+ types_to_check.filter_map do |object_type|
164
+ if (index_def = object_type.index_def)
165
165
  identify_missing_necessary_fields_for_index_def(object_type, index_def, json_schema_resolver, version)
166
166
  end
167
- end
167
+ end.flatten
168
168
  end
169
169
 
170
170
  def identify_missing_necessary_fields_for_index_def(object_type, index_def, json_schema_resolver, json_schema_version)
@@ -1,4 +1,4 @@
1
- # Copyright 2024 - 2025 Block, Inc.
1
+ # Copyright 2024 - 2026 Block, Inc.
2
2
  #
3
3
  # Use of this source code is governed by an MIT-style
4
4
  # license that can be found in the LICENSE file or at
@@ -1,4 +1,4 @@
1
- # Copyright 2024 - 2025 Block, Inc.
1
+ # Copyright 2024 - 2026 Block, Inc.
2
2
  #
3
3
  # Use of this source code is governed by an MIT-style
4
4
  # license that can be found in the LICENSE file or at
@@ -1,4 +1,4 @@
1
- # Copyright 2024 - 2025 Block, Inc.
1
+ # Copyright 2024 - 2026 Block, Inc.
2
2
  #
3
3
  # Use of this source code is governed by an MIT-style
4
4
  # license that can be found in the LICENSE file or at
@@ -1,4 +1,4 @@
1
- # Copyright 2024 - 2025 Block, Inc.
1
+ # Copyright 2024 - 2026 Block, Inc.
2
2
  #
3
3
  # Use of this source code is governed by an MIT-style
4
4
  # license that can be found in the LICENSE file or at
@@ -1,4 +1,4 @@
1
- # Copyright 2024 - 2025 Block, Inc.
1
+ # Copyright 2024 - 2026 Block, Inc.
2
2
  #
3
3
  # Use of this source code is governed by an MIT-style
4
4
  # license that can be found in the LICENSE file or at
@@ -137,10 +137,9 @@ module ElasticGraph
137
137
  #
138
138
  # Returns a tuple of the resolved source (if successful) and an error (if invalid).
139
139
  def resolve_field_source(adapter)
140
- # For now we only support one index (so we can use the first index) but someday we may need to support multiple.
141
- index = object_type.indices.first # : Index
140
+ index_def = object_type.index_def # : Index
142
141
 
143
- field_source_graphql_path_string = adapter.get_field_source(resolved_relationship.relationship, index) do |local_need|
142
+ field_source_graphql_path_string = adapter.get_field_source(resolved_relationship.relationship, index_def) do |local_need|
144
143
  relationship_name = resolved_relationship.relationship_name
145
144
 
146
145
  error = "Cannot update `#{object_type.name}` documents with data from related `#{relationship_name}` events, " \
@@ -1,4 +1,4 @@
1
- # Copyright 2024 - 2025 Block, Inc.
1
+ # Copyright 2024 - 2026 Block, Inc.
2
2
  #
3
3
  # Use of this source code is governed by an MIT-style
4
4
  # license that can be found in the LICENSE file or at
@@ -1,4 +1,4 @@
1
- # Copyright 2024 - 2025 Block, Inc.
1
+ # Copyright 2024 - 2026 Block, Inc.
2
2
  #
3
3
  # Use of this source code is governed by an MIT-style
4
4
  # license that can be found in the LICENSE file or at
@@ -1,4 +1,4 @@
1
- # Copyright 2024 - 2025 Block, Inc.
1
+ # Copyright 2024 - 2026 Block, Inc.
2
2
  #
3
3
  # Use of this source code is governed by an MIT-style
4
4
  # license that can be found in the LICENSE file or at
@@ -1,4 +1,4 @@
1
- # Copyright 2024 - 2025 Block, Inc.
1
+ # Copyright 2024 - 2026 Block, Inc.
2
2
  #
3
3
  # Use of this source code is governed by an MIT-style
4
4
  # license that can be found in the LICENSE file or at
@@ -1,4 +1,4 @@
1
- # Copyright 2024 - 2025 Block, Inc.
1
+ # Copyright 2024 - 2026 Block, Inc.
2
2
  #
3
3
  # Use of this source code is governed by an MIT-style
4
4
  # license that can be found in the LICENSE file or at
@@ -1,4 +1,4 @@
1
- # Copyright 2024 - 2025 Block, Inc.
1
+ # Copyright 2024 - 2026 Block, Inc.
2
2
  #
3
3
  # Use of this source code is governed by an MIT-style
4
4
  # license that can be found in the LICENSE file or at
@@ -27,12 +27,10 @@ module ElasticGraph
27
27
  def initialize(*args, **options)
28
28
  super(*args, **options)
29
29
  @runtime_metadata_overrides = {}
30
+ @can_configure_index = true
30
31
  resolve_fields_with :get_record_field_value
31
32
  yield self
32
-
33
- # Freeze `indices` so that the indexable status of a type does not change after instantiation.
34
- # (That would cause problems.)
35
- indices.freeze
33
+ @can_configure_index = false
36
34
  end
37
35
 
38
36
  # Converts the current type from being an _embedded_ type (that is, a type that is embedded within another indexed type) to an
@@ -69,7 +67,17 @@ module ElasticGraph
69
67
  # end
70
68
  # end
71
69
  def index(name, **settings, &block)
72
- indices.replace([Indexing::Index.new(name, settings, schema_def_state, self, &block)])
70
+ unless @can_configure_index
71
+ raise Errors::SchemaError, "Cannot define an index on `#{self.name}` after initialization is complete. " \
72
+ "Indices must be configured during initial type definition."
73
+ end
74
+
75
+ if @index_def
76
+ raise Errors::SchemaError, "Cannot define multiple indices on `#{self.name}`. " \
77
+ "Only one index per type is supported. An index named `#{@index_def.name}` has already been defined."
78
+ end
79
+
80
+ @index_def = schema_def_state.factory.new_index(name, settings, self, &block)
73
81
  end
74
82
 
75
83
  # Configures the default GraphQL resolver that will be used to resolve the fields of this type. Individual fields
@@ -85,16 +93,14 @@ module ElasticGraph
85
93
  end
86
94
  end
87
95
 
88
- # List of indices. (Currently we only store one but we may support multiple in the future).
89
- #
90
- # @private
91
- def indices
92
- @indices ||= []
96
+ # @return [Indexing::Index, nil] the defined index for this type, or nil if no index is defined
97
+ def index_def
98
+ @index_def
93
99
  end
94
100
 
95
101
  # @return [Boolean] true if this type has an index
96
102
  def indexed?
97
- indices.any?
103
+ !@index_def.nil?
98
104
  end
99
105
 
100
106
  # Abstract types are rare, so return false. This can be overridden in the host class.
@@ -182,7 +188,7 @@ module ElasticGraph
182
188
  def runtime_metadata(extra_update_targets)
183
189
  SchemaArtifacts::RuntimeMetadata::ObjectType.new(
184
190
  update_targets: derived_indexed_types.map(&:runtime_metadata_for_source_type) + [self_update_target].compact + extra_update_targets,
185
- index_definition_names: indices.map(&:name),
191
+ index_definition_names: [index_def&.name].compact,
186
192
  graphql_fields_by_name: runtime_metadata_graphql_fields_by_name,
187
193
  elasticgraph_category: nil,
188
194
  source_type: nil,
@@ -267,7 +273,7 @@ module ElasticGraph
267
273
  [field, SchemaArtifacts::RuntimeMetadata::DynamicParam.new(source_path: field, cardinality: :one)]
268
274
  end
269
275
 
270
- index_runtime_metadata = indices.first.runtime_metadata
276
+ index_runtime_metadata = index_def.runtime_metadata
271
277
 
272
278
  Indexing::UpdateTargetFactory.new_normal_indexing_update_target(
273
279
  type: name,
@@ -1,4 +1,4 @@
1
- # Copyright 2024 - 2025 Block, Inc.
1
+ # Copyright 2024 - 2026 Block, Inc.
2
2
  #
3
3
  # Use of this source code is governed by an MIT-style
4
4
  # license that can be found in the LICENSE file or at
@@ -1,4 +1,4 @@
1
- # Copyright 2024 - 2025 Block, Inc.
1
+ # Copyright 2024 - 2026 Block, Inc.
2
2
  #
3
3
  # Use of this source code is governed by an MIT-style
4
4
  # license that can be found in the LICENSE file or at
@@ -1,4 +1,4 @@
1
- # Copyright 2024 - 2025 Block, Inc.
1
+ # Copyright 2024 - 2026 Block, Inc.
2
2
  #
3
3
  # Use of this source code is governed by an MIT-style
4
4
  # license that can be found in the LICENSE file or at
@@ -1,4 +1,4 @@
1
- # Copyright 2024 - 2025 Block, Inc.
1
+ # Copyright 2024 - 2026 Block, Inc.
2
2
  #
3
3
  # Use of this source code is governed by an MIT-style
4
4
  # license that can be found in the LICENSE file or at
@@ -1,4 +1,4 @@
1
- # Copyright 2024 - 2025 Block, Inc.
1
+ # Copyright 2024 - 2026 Block, Inc.
2
2
  #
3
3
  # Use of this source code is governed by an MIT-style
4
4
  # license that can be found in the LICENSE file or at
@@ -1,4 +1,4 @@
1
- # Copyright 2024 - 2025 Block, Inc.
1
+ # Copyright 2024 - 2026 Block, Inc.
2
2
  #
3
3
  # Use of this source code is governed by an MIT-style
4
4
  # license that can be found in the LICENSE file or at
@@ -1,4 +1,4 @@
1
- # Copyright 2024 - 2025 Block, Inc.
1
+ # Copyright 2024 - 2026 Block, Inc.
2
2
  #
3
3
  # Use of this source code is governed by an MIT-style
4
4
  # license that can be found in the LICENSE file or at