elasticgraph-schema_definition 1.0.2 → 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 +1 -1
  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 +1 -1
  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 +2 -2
  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 +12 -1
  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 +8 -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 +6 -3
  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 +1 -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 +1 -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 +32 -26
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4756602b0f1d661da8c577effc6f1daa1ef0ad8cc86148f3068ebc13c676f6b8
4
- data.tar.gz: 37a2c4e7901483d9a211a9dd16a00554f8fbf9e05ba02201202a40f587ffff68
3
+ metadata.gz: 9865f28d6f21c9522e9834f4bf583e563861fa6ee08f7a7c532588c6848853e0
4
+ data.tar.gz: d00543cabfa2cb9bbdbc225de3224cd16adee14fe50a559da63299deff50b658
5
5
  SHA512:
6
- metadata.gz: cb4dd42e565f3635496d2f0df52390528814b9a0f56b9f702a910ffa850ab08a76179b088d0b72cbb08fe835e14551b26dfd4557b0e838dc482468596893417b
7
- data.tar.gz: cda65f9354c0c726a53254213f11e211b59de7dd1639cf6bb158394c1af00a6de4666707d356101e1d7a0137f324ceb21606ce05ce7b977847098111f38b5589
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
@@ -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
@@ -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
@@ -77,7 +77,7 @@ module ElasticGraph
77
77
  "Only one index per type is supported. An index named `#{@index_def.name}` has already been defined."
78
78
  end
79
79
 
80
- @index_def = Indexing::Index.new(name, settings, schema_def_state, self, &block)
80
+ @index_def = schema_def_state.factory.new_index(name, settings, self, &block)
81
81
  end
82
82
 
83
83
  # Configures the default GraphQL resolver that will be used to resolve the fields of this type. Individual fields
@@ -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
@@ -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
@@ -155,14 +155,14 @@ module ElasticGraph
155
155
  end
156
156
 
157
157
  def schema_artifact_manager
158
- require "elastic_graph/schema_definition/schema_artifact_manager"
158
+ require "elastic_graph/schema_definition/api"
159
159
 
160
160
  # :nocov: -- tests don't cover the `VERBOSE` side
161
161
  max_diff_lines = ENV["VERBOSE"] ? 999999999 : 50
162
162
  # :nocov:
163
163
 
164
- SchemaArtifactManager.new(
165
- schema_definition_results: schema_definition_results,
164
+ schema_def_api.factory.new_schema_artifact_manager(
165
+ schema_definition_results: schema_def_api.results,
166
166
  schema_artifacts_directory: @schema_artifacts_directory.to_s,
167
167
  enforce_json_schema_version: @enforce_json_schema_version,
168
168
  output: @output,
@@ -170,7 +170,7 @@ module ElasticGraph
170
170
  )
171
171
  end
172
172
 
173
- def schema_definition_results
173
+ def schema_def_api
174
174
  require "elastic_graph/schema_definition/api"
175
175
 
176
176
  API.new(
@@ -183,7 +183,7 @@ module ElasticGraph
183
183
  output: @output
184
184
  ).tap do |api|
185
185
  api.as_active_instance { load @path_to_schema.to_s }
186
- end.results
186
+ end
187
187
  end
188
188
  end
189
189
  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
@@ -18,6 +18,7 @@ require "elastic_graph/schema_definition/mixins/has_readable_to_s_and_inspect"
18
18
  require "elastic_graph/schema_definition/schema_elements/field_path"
19
19
  require "elastic_graph/schema_definition/scripting/file_system_repository"
20
20
  require "elastic_graph/support/memoizable_data"
21
+ require "elastic_graph/version"
21
22
 
22
23
  module ElasticGraph
23
24
  module SchemaDefinition
@@ -225,6 +226,7 @@ module ElasticGraph
225
226
  end
226
227
 
227
228
  SchemaArtifacts::RuntimeMetadata::Schema.new(
229
+ elasticgraph_version: ElasticGraph::VERSION,
228
230
  object_types_by_name: object_types_by_name,
229
231
  scalar_types_by_name: scalar_types_by_name,
230
232
  enum_types_by_name: enum_types_by_name,
@@ -285,6 +287,15 @@ module ElasticGraph
285
287
  update_target, errors = update_target_resolver.resolve
286
288
  accum[resolved_relationship.related_type.name] << update_target if update_target
287
289
  sourced_field_errors.concat(errors)
290
+
291
+ # Validate that has_had_multiple_sources! has been called when sourced_from is used
292
+ if (index_def = object_type.index_def) && !index_def.has_had_multiple_sources_flag
293
+ sourced_field_errors << "Type `#{object_type.name}` uses `sourced_from` fields but its index `#{index_def.name}` " \
294
+ "has not been configured with `has_had_multiple_sources!`. To resolve this, add `i.has_had_multiple_sources!` within the " \
295
+ "`t.index \"#{index_def.name}\"` block. This flag is required because indices with multiple sources can contain " \
296
+ "incomplete documents, and ElasticGraph needs to know this to apply proper filtering. Once set, this flag should remain even " \
297
+ "if you later remove all `sourced_from` fields, as the index may still contain historical incomplete documents."
298
+ end
288
299
  end
289
300
  end
290
301
  end.tap do