verquest 0.6.2 → 0.6.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +5 -0
- data/Rakefile +26 -3
- data/lib/verquest/base/private_class_methods.rb +30 -0
- data/lib/verquest/base/public_class_methods.rb +18 -9
- data/lib/verquest/configuration.rb +2 -0
- data/lib/verquest/gem_version.rb +1 -1
- data/lib/verquest/helper_methods/required_properties.rb +1 -1
- data/lib/verquest/properties/array.rb +2 -2
- data/lib/verquest/properties/base.rb +1 -1
- data/lib/verquest/properties/collection.rb +44 -5
- data/lib/verquest/properties/const.rb +2 -2
- data/lib/verquest/properties/enum.rb +2 -2
- data/lib/verquest/properties/field.rb +2 -2
- data/lib/verquest/properties/object.rb +1 -1
- data/lib/verquest/properties/one_of.rb +437 -0
- data/lib/verquest/properties/reference.rb +2 -2
- data/lib/verquest/transformer.rb +813 -48
- data/lib/verquest/version.rb +240 -11
- metadata +2 -1
|
@@ -0,0 +1,437 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Verquest
|
|
4
|
+
module Properties
|
|
5
|
+
# OneOf property type for polymorphic schemas
|
|
6
|
+
#
|
|
7
|
+
# Implements JSON Schema's oneOf keyword for defining polymorphic request structures
|
|
8
|
+
# where exactly one of multiple schemas must match. Supports optional discriminator-based
|
|
9
|
+
# schema selection using a property value to determine which schema applies.
|
|
10
|
+
#
|
|
11
|
+
# According to JSON Schema specification, oneOf validates that the data is valid against
|
|
12
|
+
# exactly one of the subschemas. The discriminator is an OpenAPI extension that helps
|
|
13
|
+
# with efficient schema resolution but is not required for basic oneOf validation.
|
|
14
|
+
#
|
|
15
|
+
# When used at the root level (without a name), it creates a "combination schema"
|
|
16
|
+
# where the entire request body can match one of the defined schemas.
|
|
17
|
+
#
|
|
18
|
+
# @example Root-level oneOf with discriminator
|
|
19
|
+
# one_of = Verquest::Properties::OneOf.new(discriminator: "type")
|
|
20
|
+
# one_of.add(Verquest::Properties::Reference.new(name: "dog", from: DogComponent))
|
|
21
|
+
# one_of.add(Verquest::Properties::Reference.new(name: "cat", from: CatComponent))
|
|
22
|
+
#
|
|
23
|
+
# @example Nested oneOf property
|
|
24
|
+
# one_of = Verquest::Properties::OneOf.new(
|
|
25
|
+
# name: :payment,
|
|
26
|
+
# discriminator: "method",
|
|
27
|
+
# required: true
|
|
28
|
+
# )
|
|
29
|
+
#
|
|
30
|
+
# @example oneOf without discriminator (pure JSON Schema validation)
|
|
31
|
+
# one_of = Verquest::Properties::OneOf.new(name: :value)
|
|
32
|
+
# # Validates that exactly one schema matches
|
|
33
|
+
class OneOf < Base
|
|
34
|
+
# JSON Schema for null type, used when nullable is true
|
|
35
|
+
NULL_TYPE_SCHEMA = {"type" => "null"}.freeze
|
|
36
|
+
|
|
37
|
+
# @return [String, nil] The discriminator property name for schema selection
|
|
38
|
+
attr_reader :discriminator
|
|
39
|
+
|
|
40
|
+
# Initialize a new OneOf property
|
|
41
|
+
#
|
|
42
|
+
# @param name [String, Symbol, nil] The property name, or nil for root-level oneOf
|
|
43
|
+
# @param discriminator [String, Symbol, nil] The property name used to discriminate between schemas.
|
|
44
|
+
# When omitted, the transformer infers the variant by validating against each schema.
|
|
45
|
+
# @param required [Boolean, Array<Symbol>] Whether this property is required, or array of dependency names
|
|
46
|
+
# @param nullable [Boolean] Whether this property can be null
|
|
47
|
+
# @param map [String, nil] The mapping path for this property
|
|
48
|
+
def initialize(name: nil, discriminator: nil, required: false, nullable: false, map: nil)
|
|
49
|
+
@name = name&.to_s
|
|
50
|
+
@required = required
|
|
51
|
+
@nullable = nullable
|
|
52
|
+
@map = map
|
|
53
|
+
@discriminator = discriminator&.to_s
|
|
54
|
+
@schemas = {}
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Add a schema option to this oneOf
|
|
58
|
+
#
|
|
59
|
+
# Both Reference and Object properties are allowed at any level.
|
|
60
|
+
# Object properties define inline schemas directly within the oneOf.
|
|
61
|
+
#
|
|
62
|
+
# @param schema [Verquest::Properties::Reference, Verquest::Properties::Object] The schema to add
|
|
63
|
+
# @raise [ArgumentError] If schema is neither a Reference nor an Object
|
|
64
|
+
# @return [Verquest::Properties::Base] The added schema
|
|
65
|
+
def add(schema)
|
|
66
|
+
unless schema.is_a?(Verquest::Properties::Reference) || schema.is_a?(Verquest::Properties::Object)
|
|
67
|
+
raise ArgumentError, "Must be a Reference or Object property"
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
schemas[schema.name] = schema
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# Generate JSON schema definition for this oneOf property
|
|
74
|
+
#
|
|
75
|
+
# @return [Hash] The schema definition with oneOf array and optional discriminator
|
|
76
|
+
def to_schema
|
|
77
|
+
freeze_schemas
|
|
78
|
+
wrap_schema(build_schema_with_refs)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# Generate validation schema for this oneOf property
|
|
82
|
+
#
|
|
83
|
+
# Unlike to_schema which uses $ref, the validation schema includes
|
|
84
|
+
# the full inline schema definitions for each option.
|
|
85
|
+
#
|
|
86
|
+
# @param version [String, nil] The version to generate validation schema for
|
|
87
|
+
# @return [Hash] The validation schema with inline schema definitions
|
|
88
|
+
def to_validation_schema(version: nil)
|
|
89
|
+
freeze_schemas
|
|
90
|
+
wrap_schema(build_validation_schema(version: version))
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# Create mapping for this oneOf property
|
|
94
|
+
#
|
|
95
|
+
# For oneOf schemas, the mapping is keyed by discriminator value so the
|
|
96
|
+
# transformer can select the appropriate mapping based on the input.
|
|
97
|
+
# Each discriminator value maps to a hash of source => target path mappings.
|
|
98
|
+
#
|
|
99
|
+
# For nested oneOf (with a name), the property name is included in the path prefixes.
|
|
100
|
+
# For root-level oneOf (name is nil), paths start from the root.
|
|
101
|
+
#
|
|
102
|
+
# The `map` parameter on oneOf affects the target path prefix for all contained schemas.
|
|
103
|
+
#
|
|
104
|
+
# When no discriminator is set, the transformer will infer the variant by validating
|
|
105
|
+
# the input against each schema and selecting the one that matches.
|
|
106
|
+
#
|
|
107
|
+
# @param key_prefix [Array<String>] Prefix for the source key paths
|
|
108
|
+
# @param value_prefix [Array<String>] Prefix for the target value paths
|
|
109
|
+
# @param mapping [Hash] The mapping hash to be updated (discriminator value => path mappings)
|
|
110
|
+
# @param version [String, nil] The version to create mapping for
|
|
111
|
+
# @return [void]
|
|
112
|
+
def mapping(key_prefix:, value_prefix:, mapping:, version: nil)
|
|
113
|
+
freeze_schemas
|
|
114
|
+
source_prefix = compute_source_prefix(key_prefix)
|
|
115
|
+
target_prefix = compute_target_prefix(value_prefix)
|
|
116
|
+
|
|
117
|
+
build_variant_mappings(mapping, source_prefix, target_prefix, version)
|
|
118
|
+
store_discriminator_path(mapping, source_prefix)
|
|
119
|
+
store_variant_schemas(mapping, version) unless discriminator
|
|
120
|
+
store_nullable_metadata(mapping, target_prefix:) if nullable
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
# Returns validation schemas for all variants
|
|
124
|
+
#
|
|
125
|
+
# Used by the Transformer to infer which variant matches when no discriminator is set.
|
|
126
|
+
#
|
|
127
|
+
# @param version [String, nil] The version for schema resolution
|
|
128
|
+
# @return [Hash<String, Hash>] Variant name => validation schema mapping
|
|
129
|
+
def variant_schemas(version: nil)
|
|
130
|
+
freeze_schemas
|
|
131
|
+
schemas.each_with_object({}) do |(name, schema), result|
|
|
132
|
+
result[name] = schema.to_validation_schema(version: version)[schema.name]
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
private
|
|
137
|
+
|
|
138
|
+
attr_reader :schemas
|
|
139
|
+
|
|
140
|
+
# Freezes the schemas hash to prevent further modifications
|
|
141
|
+
# This is called on first read access to ensure immutability after setup
|
|
142
|
+
#
|
|
143
|
+
# @return [void]
|
|
144
|
+
def freeze_schemas
|
|
145
|
+
schemas.freeze unless schemas.frozen?
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
# Check if this is a root-level oneOf (no property name)
|
|
149
|
+
#
|
|
150
|
+
# @return [Boolean] true if this oneOf is at the root level
|
|
151
|
+
def root_level?
|
|
152
|
+
name.nil?
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
# Wraps the schema hash with the property name if present
|
|
156
|
+
#
|
|
157
|
+
# @param schema [Hash] The schema to wrap
|
|
158
|
+
# @return [Hash] The schema, optionally wrapped with the property name
|
|
159
|
+
def wrap_schema(schema)
|
|
160
|
+
root_level? ? schema : {name => schema}
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
# Computes the source path prefix for mapping keys
|
|
164
|
+
#
|
|
165
|
+
# @param key_prefix [Array<String>] The current key prefix
|
|
166
|
+
# @return [Array<String>] The effective key prefix including the property name if present
|
|
167
|
+
def compute_source_prefix(key_prefix)
|
|
168
|
+
root_level? ? key_prefix : key_prefix + [name]
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
# Computes the target path prefix for mapping values
|
|
172
|
+
#
|
|
173
|
+
# @param value_prefix [Array<String>] The current value prefix
|
|
174
|
+
# @return [Array<String>] The effective value prefix based on map or name
|
|
175
|
+
def compute_target_prefix(value_prefix)
|
|
176
|
+
return parse_absolute_path(@map) if absolute_path?(@map)
|
|
177
|
+
return value_prefix + parse_relative_path(@map) if @map
|
|
178
|
+
|
|
179
|
+
root_level? ? value_prefix : value_prefix + [name]
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
# Computes the target prefix for a specific reference's mapping
|
|
183
|
+
#
|
|
184
|
+
# @param reference_map [String, nil] The map parameter from the reference
|
|
185
|
+
# @param base_prefix [Array<String>] The base value prefix
|
|
186
|
+
# @return [Array<String>] The target prefix as an array of path segments
|
|
187
|
+
def compute_reference_target_prefix(reference_map, base_prefix)
|
|
188
|
+
return base_prefix if reference_map.nil?
|
|
189
|
+
return parse_absolute_path(reference_map) if absolute_path?(reference_map)
|
|
190
|
+
|
|
191
|
+
base_prefix + parse_relative_path(reference_map)
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
# Builds variant mappings for each schema option
|
|
195
|
+
#
|
|
196
|
+
# Handles both Reference and Object schemas:
|
|
197
|
+
# - Reference: delegates to the referenced schema's mapping
|
|
198
|
+
# - Object: builds mapping from child properties directly
|
|
199
|
+
#
|
|
200
|
+
# @param mapping [Hash] The mapping hash to populate
|
|
201
|
+
# @param source_prefix [Array<String>] Source path prefix
|
|
202
|
+
# @param target_prefix [Array<String>] Target path prefix
|
|
203
|
+
# @param version [String, nil] The version for schema resolution
|
|
204
|
+
# @return [void]
|
|
205
|
+
def build_variant_mappings(mapping, source_prefix, target_prefix, version)
|
|
206
|
+
schemas.each_value do |schema|
|
|
207
|
+
if schema.is_a?(Verquest::Properties::Reference)
|
|
208
|
+
build_reference_variant_mapping(mapping, schema, source_prefix, target_prefix, version)
|
|
209
|
+
elsif schema.is_a?(Verquest::Properties::Object)
|
|
210
|
+
build_object_variant_mapping(mapping, schema, source_prefix, target_prefix, version)
|
|
211
|
+
end
|
|
212
|
+
end
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
# Builds mapping for a Reference variant
|
|
216
|
+
#
|
|
217
|
+
# @param mapping [Hash] The mapping hash to populate
|
|
218
|
+
# @param schema [Verquest::Properties::Reference] The reference schema
|
|
219
|
+
# @param source_prefix [Array<String>] Source path prefix
|
|
220
|
+
# @param target_prefix [Array<String>] Target path prefix
|
|
221
|
+
# @param version [String, nil] The version for schema resolution
|
|
222
|
+
# @return [void]
|
|
223
|
+
def build_reference_variant_mapping(mapping, schema, source_prefix, target_prefix, version)
|
|
224
|
+
reference_mapping = schema.send(:from).mapping(version: version)
|
|
225
|
+
reference_map = schema.send(:map)
|
|
226
|
+
variant_target_prefix = compute_reference_target_prefix(reference_map, target_prefix)
|
|
227
|
+
|
|
228
|
+
mapping[schema.name] = build_prefixed_mapping(
|
|
229
|
+
reference_mapping,
|
|
230
|
+
source_prefix,
|
|
231
|
+
variant_target_prefix
|
|
232
|
+
)
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
# Builds mapping for an inline Object variant
|
|
236
|
+
#
|
|
237
|
+
# Unlike nested objects, inline oneOf variants map their properties directly
|
|
238
|
+
# under the oneOf property path (not under oneOf/variant_name).
|
|
239
|
+
# This mirrors how Reference variants work.
|
|
240
|
+
#
|
|
241
|
+
# @param mapping [Hash] The mapping hash to populate
|
|
242
|
+
# @param schema [Verquest::Properties::Object] The object schema
|
|
243
|
+
# @param source_prefix [Array<String>] Source path prefix
|
|
244
|
+
# @param target_prefix [Array<String>] Target path prefix
|
|
245
|
+
# @param version [String, nil] The version for schema resolution
|
|
246
|
+
# @return [void]
|
|
247
|
+
def build_object_variant_mapping(mapping, schema, source_prefix, target_prefix, version)
|
|
248
|
+
object_mapping = {}
|
|
249
|
+
object_map = schema.send(:map)
|
|
250
|
+
variant_target_prefix = compute_reference_target_prefix(object_map, target_prefix)
|
|
251
|
+
|
|
252
|
+
# Build mapping from object's child properties
|
|
253
|
+
# Properties are mapped directly under source_prefix (not source_prefix + object_name)
|
|
254
|
+
# to match how Reference variants work
|
|
255
|
+
schema.send(:properties).each_value do |property|
|
|
256
|
+
property.mapping(
|
|
257
|
+
key_prefix: source_prefix,
|
|
258
|
+
value_prefix: variant_target_prefix,
|
|
259
|
+
mapping: object_mapping,
|
|
260
|
+
version: version
|
|
261
|
+
)
|
|
262
|
+
end
|
|
263
|
+
|
|
264
|
+
mapping[schema.name] = object_mapping
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
# Builds a mapping hash with prefixes applied to all keys and values
|
|
268
|
+
#
|
|
269
|
+
# @param base_mapping [Hash] The source mapping from the referenced schema
|
|
270
|
+
# @param source_prefix [Array<String>] Prefix for source keys
|
|
271
|
+
# @param target_prefix [Array<String>] Prefix for target values
|
|
272
|
+
# @return [Hash] The mapping with prefixes applied
|
|
273
|
+
def build_prefixed_mapping(base_mapping, source_prefix, target_prefix)
|
|
274
|
+
base_mapping.each_with_object({}) do |(source_key, target_value), result|
|
|
275
|
+
result[join_path(source_prefix, source_key)] = join_path(target_prefix, target_value)
|
|
276
|
+
end
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
# Stores the discriminator path in the mapping for nested oneOf
|
|
280
|
+
#
|
|
281
|
+
# For nested oneOf (with a name) or oneOf inside a collection (source_prefix is not empty),
|
|
282
|
+
# stores the discriminator path so the transformer knows where to look for the value.
|
|
283
|
+
#
|
|
284
|
+
# @param mapping [Hash] The mapping hash to update
|
|
285
|
+
# @param source_prefix [Array<String>] The source path prefix
|
|
286
|
+
# @return [void]
|
|
287
|
+
def store_discriminator_path(mapping, source_prefix)
|
|
288
|
+
return unless discriminator
|
|
289
|
+
# Skip only for true root-level oneOf (no name AND no prefix from collection)
|
|
290
|
+
return if root_level? && source_prefix.empty?
|
|
291
|
+
|
|
292
|
+
mapping["_discriminator"] = join_path(source_prefix, discriminator)
|
|
293
|
+
end
|
|
294
|
+
|
|
295
|
+
# Stores variant schemas in the mapping for schema-based inference
|
|
296
|
+
#
|
|
297
|
+
# When no discriminator is set, the transformer needs access to the validation
|
|
298
|
+
# schemas to determine which variant matches the input data.
|
|
299
|
+
#
|
|
300
|
+
# @param mapping [Hash] The mapping hash to update
|
|
301
|
+
# @param version [String, nil] The version for schema resolution
|
|
302
|
+
# @return [void]
|
|
303
|
+
def store_variant_schemas(mapping, version)
|
|
304
|
+
mapping["_variant_schemas"] = variant_schemas(version: version)
|
|
305
|
+
mapping["_variant_path"] = name unless root_level?
|
|
306
|
+
end
|
|
307
|
+
|
|
308
|
+
# Stores nullable metadata in the mapping
|
|
309
|
+
#
|
|
310
|
+
# When nullable is true, the transformer needs to know to allow null values
|
|
311
|
+
# without attempting variant resolution.
|
|
312
|
+
#
|
|
313
|
+
# @param mapping [Hash] The mapping hash to update
|
|
314
|
+
# @param target_prefix [Array<String>] The target path prefix for the oneOf property
|
|
315
|
+
# @return [void]
|
|
316
|
+
def store_nullable_metadata(mapping, target_prefix:)
|
|
317
|
+
mapping["_nullable"] = true
|
|
318
|
+
return if root_level?
|
|
319
|
+
|
|
320
|
+
mapping["_nullable_path"] = name
|
|
321
|
+
mapping["_nullable_target_path"] = target_prefix.join("/")
|
|
322
|
+
end
|
|
323
|
+
|
|
324
|
+
# Joins path segments into a slash-separated path string
|
|
325
|
+
#
|
|
326
|
+
# @param prefix [Array<String>] The path prefix segments
|
|
327
|
+
# @param suffix [String] The path suffix
|
|
328
|
+
# @return [String] The combined path
|
|
329
|
+
def join_path(prefix, suffix)
|
|
330
|
+
prefix.empty? ? suffix : "#{prefix.join("/")}/#{suffix}"
|
|
331
|
+
end
|
|
332
|
+
|
|
333
|
+
# Checks if a path is absolute (starts with /)
|
|
334
|
+
#
|
|
335
|
+
# @param path [String, nil] The path to check
|
|
336
|
+
# @return [Boolean] true if the path is absolute
|
|
337
|
+
def absolute_path?(path)
|
|
338
|
+
path&.start_with?("/")
|
|
339
|
+
end
|
|
340
|
+
|
|
341
|
+
# Parses an absolute path into segments
|
|
342
|
+
#
|
|
343
|
+
# @param path [String] The absolute path to parse
|
|
344
|
+
# @return [Array<String>] The path segments
|
|
345
|
+
def parse_absolute_path(path)
|
|
346
|
+
path.delete_prefix("/").split("/").reject(&:empty?)
|
|
347
|
+
end
|
|
348
|
+
|
|
349
|
+
# Parses a relative path into segments
|
|
350
|
+
#
|
|
351
|
+
# @param path [String] The relative path to parse
|
|
352
|
+
# @return [Array<String>] The path segments
|
|
353
|
+
def parse_relative_path(path)
|
|
354
|
+
path.split("/")
|
|
355
|
+
end
|
|
356
|
+
|
|
357
|
+
# Returns the JSON Schema keyword for this property type
|
|
358
|
+
#
|
|
359
|
+
# @return [String] Always returns "oneOf"
|
|
360
|
+
def schema_keyword
|
|
361
|
+
"oneOf"
|
|
362
|
+
end
|
|
363
|
+
|
|
364
|
+
# Builds the JSON schema structure with $ref references
|
|
365
|
+
#
|
|
366
|
+
# @return [Hash] Schema with oneOf array and optional discriminator
|
|
367
|
+
def build_schema_with_refs
|
|
368
|
+
schema = {schema_keyword => collect_schema_refs}
|
|
369
|
+
add_discriminator_to_schema(schema)
|
|
370
|
+
schema
|
|
371
|
+
end
|
|
372
|
+
|
|
373
|
+
# Builds the validation schema structure with inline definitions
|
|
374
|
+
#
|
|
375
|
+
# Unlike the documentation schema, the validation schema omits the discriminator
|
|
376
|
+
# since it's an OpenAPI extension that JSON Schema validators ignore.
|
|
377
|
+
# Validators validate against the oneOf array directly.
|
|
378
|
+
#
|
|
379
|
+
# @param version [String, nil] The version to generate validation schema for
|
|
380
|
+
# @return [Hash] Validation schema with oneOf array (no discriminator)
|
|
381
|
+
def build_validation_schema(version:)
|
|
382
|
+
{schema_keyword => collect_inline_schemas(version)}
|
|
383
|
+
end
|
|
384
|
+
|
|
385
|
+
# Collects $ref schema references for all variants
|
|
386
|
+
#
|
|
387
|
+
# @return [Array<Hash>] Array of schema references
|
|
388
|
+
def collect_schema_refs
|
|
389
|
+
refs = schemas.values.map { |schema| schema.to_schema[schema.name] }
|
|
390
|
+
refs << NULL_TYPE_SCHEMA if nullable
|
|
391
|
+
refs
|
|
392
|
+
end
|
|
393
|
+
|
|
394
|
+
# Collects inline schema definitions for all variants
|
|
395
|
+
#
|
|
396
|
+
# @param version [String, nil] The version for schema resolution
|
|
397
|
+
# @return [Array<Hash>] Array of inline schema definitions
|
|
398
|
+
def collect_inline_schemas(version)
|
|
399
|
+
inline_schemas = schemas.values.map { |schema| schema.to_validation_schema(version: version)[schema.name] }
|
|
400
|
+
inline_schemas << NULL_TYPE_SCHEMA if nullable
|
|
401
|
+
inline_schemas
|
|
402
|
+
end
|
|
403
|
+
|
|
404
|
+
# Adds discriminator information to the schema if present
|
|
405
|
+
#
|
|
406
|
+
# Only Reference schemas are included in the discriminator mapping since
|
|
407
|
+
# Objects don't have $ref. This follows OpenAPI spec where discriminator
|
|
408
|
+
# mapping contains only $ref strings.
|
|
409
|
+
#
|
|
410
|
+
# @param schema [Hash] The schema to modify
|
|
411
|
+
# @return [void]
|
|
412
|
+
def add_discriminator_to_schema(schema)
|
|
413
|
+
return unless discriminator
|
|
414
|
+
|
|
415
|
+
schema["discriminator"] = {
|
|
416
|
+
"propertyName" => discriminator,
|
|
417
|
+
"mapping" => build_discriminator_mapping
|
|
418
|
+
}
|
|
419
|
+
end
|
|
420
|
+
|
|
421
|
+
# Builds the discriminator mapping with $ref values
|
|
422
|
+
#
|
|
423
|
+
# Only Reference schemas are included since Objects don't have $ref.
|
|
424
|
+
# This follows OpenAPI spec where discriminator mapping contains only $ref strings.
|
|
425
|
+
#
|
|
426
|
+
# @return [Hash] The discriminator value to $ref mapping
|
|
427
|
+
def build_discriminator_mapping
|
|
428
|
+
schemas.each_with_object({}) do |(name, schema), mapping|
|
|
429
|
+
# Only include References in discriminator mapping (Objects don't have $ref)
|
|
430
|
+
next unless schema.is_a?(Verquest::Properties::Reference)
|
|
431
|
+
|
|
432
|
+
mapping[name] = schema.to_schema[name]["$ref"]
|
|
433
|
+
end
|
|
434
|
+
end
|
|
435
|
+
end
|
|
436
|
+
end
|
|
437
|
+
end
|
|
@@ -80,8 +80,8 @@ module Verquest
|
|
|
80
80
|
# @param key_prefix [Array<String>] Prefix for the source key
|
|
81
81
|
# @param value_prefix [Array<String>] Prefix for the target value
|
|
82
82
|
# @param mapping [Hash] The mapping hash to be updated
|
|
83
|
-
# @param version [String
|
|
84
|
-
# @return [
|
|
83
|
+
# @param version [String] The version to create mapping for
|
|
84
|
+
# @return [void]
|
|
85
85
|
def mapping(key_prefix:, value_prefix:, mapping:, version:)
|
|
86
86
|
reference_mapping = from.mapping(version:, property:).dup
|
|
87
87
|
value_key_prefix = mapping_value_key(value_prefix:)
|