verquest 0.5.0 → 0.6.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b9349b2773c4a03024805d78257b1e763ffb87b87f27726620e343395c683aa0
4
- data.tar.gz: ec2b70a4a10c3314ca27283776138f85b53b245d88869de39e450ca2eb2064de
3
+ metadata.gz: 92e6047d9812ae82cf55b5d0512c459a61306c7b2cc78c9cd224e2b52b4b716c
4
+ data.tar.gz: db8943d346e30972f3b6b516d9365d7ef37dedf89fa7f4a09c5db4cb1adbe545
5
5
  SHA512:
6
- metadata.gz: 0d0042f959285f4253c7802166ab64d53b7013d765bfe954fd68a8ab46bb59f162512a285aca11c77e86a8e6b5ce36445f47e4e9530fcaa0010e8c6cadcefdf2
7
- data.tar.gz: 06bbfceb1c989e1e3eabb20e495790ac35934e1cb4687e71960315c3e64d3a30b42b345c03d19d32be921b75550a6fef002d8ba44018ded8f7c9a3af73d920f0
6
+ metadata.gz: 0163416a3ea0f4d5cb5619b74e31ca7f2999ddccba55091d8fa8f10244a36eeb59dadd1b6d9eae6bd22d1f49e5ea7213aeb42218731f248be69d54c2127bb216
7
+ data.tar.gz: ee7adc256954aafa194a3175f50649479a8f45292d8bed51cf076f17c1d0693fbe7099e64675d249448c1e66cb9b1dce4749da71e76f36fc2d976b7387f23382
data/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [0.6.0] - 2025-07-18
4
+
5
+ ### Breaking Changes
6
+ - **BREAKING:** Switching to slash notation for mapping to improve consistency with how properties are referenced in JSON Schema. Before: `example.nested.property`, now: `example/nested/property`. ([#12](https://github.com/CiTroNaK/verquest/pull/12), [@CiTroNaK](https://github.com/CiTroNaK))
7
+
8
+ ### New Features
9
+ - Add support for `enum` properties. ([#13](https://github.com/CiTroNaK/verquest/pull/13), [@CiTroNaK](https://github.com/CiTroNaK))
10
+ - Add support for inverted mapping, that can be used to map internal structure to external representation (e.g., for errors). ([#10](https://github.com/CiTroNaK/verquest/pull/10), [@CiTroNaK](https://github.com/CiTroNaK))
11
+ - Add support for constants in the schema, allowing to define fixed values for properties. ([#11](https://github.com/CiTroNaK/verquest/pull/11), [@CiTroNaK](https://github.com/CiTroNaK))
12
+
3
13
  ## [0.5.0] - 2025-07-01
4
14
 
5
15
  ### Fixed
data/README.md CHANGED
@@ -8,18 +8,18 @@ Verquest is a Ruby gem that offers an elegant solution for versioning API reques
8
8
  - Defining versioned request structures
9
9
  - Gracefully handling API versioning
10
10
  - Mapping between external and internal parameter structures
11
- - Validating parameters against [JSON Schema](https://json-schema.org/learn)
11
+ - Validating parameters against [JSON Schema](https://json-schema.org/)
12
12
  - Generating components for OpenAPI documentation
13
- - Mapping error keys back to the external API structure (planned feature)
13
+ - Mapping error keys back to the external API structure
14
14
 
15
- > The gem is still in development. Until version 1.0, the API may change. There are some features like `oneOf`, `anyOf`, `allOf` that are not implemented yet.
15
+ > The gem is still in development. Until version 1.0, the API may change. There are some features like `oneOf`, `anyOf`, `allOf` that are not implemented yet. See open [issues](https://github.com/CiTroNaK/verquest/issues?q=sort:updated-desc%20is:issue%20is:open%20label:enhancement).
16
16
 
17
17
  ## Installation
18
18
 
19
19
  Add this line to your application's Gemfile:
20
20
 
21
21
  ```ruby
22
- gem "verquest", "~> 0.5"
22
+ gem "verquest", "~> 0.6"
23
23
  ```
24
24
 
25
25
  And then execute:
@@ -75,7 +75,7 @@ class UserCreateRequest < Verquest::Base
75
75
  end
76
76
  end
77
77
 
78
- field :role, type: :string, description: "Role of the user", enum: %w[member manager], default: "member"
78
+ enum :role, values: %w[member manager], default: "member", description: "Role of the user", required: true
79
79
 
80
80
  object :profile_details do
81
81
  field :bio, type: :string, description: "Short biography of the user"
@@ -89,6 +89,8 @@ class UserCreateRequest < Verquest::Base
89
89
  end
90
90
  end
91
91
  end
92
+
93
+ const :company, value: "Awesome Inc."
92
94
  end
93
95
  end
94
96
  ```
@@ -130,7 +132,7 @@ Output:
130
132
  {
131
133
  "type" => "object",
132
134
  "description" => "User Create Request",
133
- "required" => ["first_name", "last_name", "email", "address"],
135
+ "required" => ["first_name", "last_name", "email", "address", "role"],
134
136
  "properties" => {
135
137
  "first_name" => {"type" => "string", "description" => "The first name of the user", "maxLength" => 50},
136
138
  "last_name" => {"type" => "string", "description" => "The last name of the user", "maxLength" => 50},
@@ -151,10 +153,9 @@ Output:
151
153
  "description" => "Permissions associated with the user"
152
154
  },
153
155
  "role" => {
154
- "type" => "string",
155
- "description" => "Role of the user",
156
- "enum" => ["member", "manager"],
157
- "default" => "member"
156
+ "enum" => ["member", "manager"],
157
+ "default" => "member",
158
+ "description" => "Role of the user"
158
159
  },
159
160
  "profile_details" => {
160
161
  "type" => "object",
@@ -172,7 +173,8 @@ Output:
172
173
  "description" => "Some social networks"
173
174
  }
174
175
  }
175
- }
176
+ },
177
+ "company" => {"const" => "Awesome Inc."}
176
178
  },
177
179
  "additionalProperties" => false
178
180
  }
@@ -191,7 +193,7 @@ Output:
191
193
  {
192
194
  "type" => "object",
193
195
  "description" => "User Create Request",
194
- "required" => ["first_name", "last_name", "email", "address"],
196
+ "required" => ["first_name", "last_name", "email", "address", "role"],
195
197
  "properties" => {
196
198
  "first_name" => {"type" => "string", "description" => "The first name of the user", "maxLength" => 50},
197
199
  "last_name" => {"type" => "string", "description" => "The last name of the user", "maxLength" => 50},
@@ -222,10 +224,9 @@ Output:
222
224
  "description" => "Permissions associated with the user"
223
225
  },
224
226
  "role" => {
225
- "type" => "string",
226
- "description" => "Role of the user",
227
227
  "enum" => ["member", "manager"],
228
- "default" => "member"
228
+ "default" => "member",
229
+ "description" => "Role of the user"
229
230
  },
230
231
  "profile_details" => {"type" => "object",
231
232
  "required" => [],
@@ -240,7 +241,8 @@ Output:
240
241
  "mastodon" => {"type" => "string", "format" => "uri", "description" => "Mastodon profile URL"}
241
242
  },
242
243
  "description" => "Some social networks"}
243
- }
244
+ },
245
+ "company" => {"const" => "Awesome Inc."}
244
246
  }
245
247
  },
246
248
  "additionalProperties" => false
@@ -265,10 +267,12 @@ The JSON schema can be used for both validation of incoming parameters and for g
265
267
  #### Component types
266
268
 
267
269
  - `field`: Represents a scalar value (string, integer, boolean, etc.).
270
+ - `enum`: Represents a property with a limited set of values (enumeration).
268
271
  - `object`: Represents a JSON object with properties.
269
272
  - `array`: Represents a JSON array with scalar items.
270
273
  - `collection`: Represents a array of objects defined manually or by a reference to another request.
271
274
  - `reference`: Represents a reference to another request, allowing you to reuse existing request structures.
275
+ - `const`: Represents a [constant](https://json-schema.org/understanding-json-schema/reference/const#constant-values) value that is always present in the request.
272
276
 
273
277
  #### Helper methods
274
278
 
@@ -276,7 +280,7 @@ The JSON schema can be used for both validation of incoming parameters and for g
276
280
  - `schema_options`: Allows you to set additional options for the JSON Schema, such as `additional_properties` for request or per version. All fields (except `reference`) can be defined with options like `required`, `format`, `min_lenght`, `max_length`, etc. all in snake case.
277
281
  - `with_options`: Allows you to define multiple fields with the same options, reducing repetition.
278
282
 
279
- ### Required properties
283
+ #### Required properties
280
284
 
281
285
  You can define required properties in your request schema by setting the `required` option to `true`, or provide a list of dependent required properties. This feature is based on the latest [JSON Schema specification](https://json-schema.org/understanding-json-schema/reference/conditionals#dependentRequired), which is also used in OpenAPI 3.1.
282
286
 
@@ -538,9 +542,28 @@ Will be transformed to:
538
542
 
539
543
  What you can use:
540
544
  - `/` to reference the root of the request structure
541
- - `nested.structure` use dot notation to reference nested structures
545
+ - `nested/structure` use slash notation to reference nested structures
542
546
  - if the `map` is not set, the field name will be used as the key in the internal structure
543
547
 
548
+ To get the mapping to map the request structure back to the external API structure, you can use the `external_mapping` method:
549
+
550
+ ```ruby
551
+ UserCreateRequest.external_mapping(version: "2025-06")
552
+ ```
553
+
554
+ Will produce the following mapping:
555
+
556
+ ```ruby
557
+ {
558
+ "name" => "full_name",
559
+ "email" => "email",
560
+ "phone" => "phone",
561
+ "address_street" => "address/street",
562
+ "address_city" => "address/city",
563
+ "address_zip" => "address/postal_code"
564
+ }
565
+ ```
566
+
544
567
  There are some limitations and the implementation can be improved, but it should works for most common use cases.
545
568
 
546
569
  See the mapping test (in `test/verquest/base_test.rb`) for more examples of mapping.
@@ -586,7 +609,7 @@ end
586
609
 
587
610
  ## Documentation
588
611
 
589
- For detailed documentation, please visit the [YARD documentation](https://www.rubydoc.info/gems/verquest/0.5.0/).
612
+ For detailed documentation, please visit the [YARD documentation](https://www.rubydoc.info/gems/verquest/0.6.0/).
590
613
 
591
614
  ## Development
592
615
 
@@ -138,6 +138,42 @@ module Verquest
138
138
  current_scope.add(field)
139
139
  end
140
140
 
141
+ # Defines a new enum property for the current version scope
142
+ #
143
+ # @param name [Symbol] The name of the enum
144
+ # @param values [Array] The possible values for the enum
145
+ # @param map [String, nil] An optional mapping to another property
146
+ # @param required [Boolean, Array<Symbol>] Whether the enum is required
147
+ # @param nullable [Boolean] Whether the enum can be null
148
+ # @param schema_options [Hash] Additional schema options for the enum
149
+ # @return [void]
150
+ def enum(name, values:, map: nil, required: nil, nullable: nil, **schema_options)
151
+ camelize(schema_options)
152
+
153
+ required = default_options.fetch(:required, false) if required.nil?
154
+ nullable = default_options.fetch(:nullable, false) if nullable.nil?
155
+ schema_options = default_options.except(:required, :nullable).merge(schema_options)
156
+
157
+ enum_property = Properties::Enum.new(name:, values:, map:, required:, nullable:, **schema_options)
158
+ current_scope.add(enum_property)
159
+ end
160
+
161
+ # Defines a new constant property for the current version scope
162
+ #
163
+ # @param name [Symbol] The name of the constant
164
+ # @param value [Object] The value of the constant
165
+ # @param map [String, nil] An optional mapping to another constant
166
+ # @param required [Boolean, Array<Symbol>] Whether the constant is required
167
+ # @param schema_options [Hash] Additional schema options for the constant
168
+ # @return [void]
169
+ def const(name, value:, map: nil, required: nil, **schema_options)
170
+ camelize(schema_options)
171
+ required = default_options.fetch(:required, false) if required.nil?
172
+
173
+ const = Properties::Const.new(name:, value:, map:, required:, **schema_options)
174
+ current_scope.add(const)
175
+ end
176
+
141
177
  # Defines a new object for the current version scope
142
178
  #
143
179
  # @param name [Symbol] The name of the object
@@ -102,6 +102,18 @@ module Verquest
102
102
  end
103
103
  end
104
104
 
105
+ # Returns the external mapping for a specific version
106
+ #
107
+ # This method returns a mapping hash that translates from internal attribute names back to external parameter names.
108
+ #
109
+ # @param version [String, nil] Specific version to use, defaults to configuration setting
110
+ # @return [Hash] The inverted mapping configuration where keys are internal names and values are external names
111
+ # @see #mapping
112
+ def external_mapping(version: nil)
113
+ version = resolve(version)
114
+ version.external_mapping
115
+ end
116
+
105
117
  # Returns the JSON reference for the request or a specific property
106
118
  #
107
119
  # @param property [String, Symbol, nil] Specific property to retrieve reference for
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Verquest
4
- GEM_VERSION = "0.5.0"
4
+ GEM_VERSION = "0.6.0"
5
5
  end
@@ -75,7 +75,7 @@ module Verquest
75
75
  # @param version [String, nil] The version to create mapping for, defaults to configuration setting
76
76
  # @return [Hash] The updated mapping hash
77
77
  def mapping(key_prefix:, value_prefix:, mapping:, version: nil)
78
- mapping[(key_prefix + [name]).join(".")] = mapping_value_key(value_prefix:)
78
+ mapping[(key_prefix + [name]).join("/")] = mapping_value_key(value_prefix:)
79
79
  end
80
80
 
81
81
  private
@@ -67,13 +67,13 @@ module Verquest
67
67
  # @return [String] The target mapping key
68
68
  def mapping_value_key(value_prefix:, collection: false)
69
69
  value_key = if map.nil?
70
- (value_prefix + [name]).join(".")
70
+ (value_prefix + [name]).join("/")
71
71
  elsif map == "/"
72
72
  ""
73
73
  elsif map.start_with?("/")
74
74
  map.gsub(%r{^/}, "")
75
75
  else
76
- (value_prefix + map.split(".")).join(".")
76
+ (value_prefix + map.split("/")).join("/")
77
77
  end
78
78
 
79
79
  if collection
@@ -93,9 +93,9 @@ module Verquest
93
93
  elsif map == "/"
94
94
  []
95
95
  elsif map.start_with?("/")
96
- map.gsub(%r{^/}, "").split(".")
96
+ map.gsub(%r{^/}, "").split("/")
97
97
  else
98
- value_prefix + map.split(".")
98
+ value_prefix + map.split("/")
99
99
  end
100
100
 
101
101
  if collection && value_prefix.any?
@@ -142,8 +142,8 @@ module Verquest
142
142
  value_key_prefix = mapping_value_key(value_prefix: value_prefix, collection: true)
143
143
 
144
144
  reference_mapping = item.mapping(version:).dup
145
- reference_mapping.transform_keys! { "#{(key_prefix + [name]).join(".")}[].#{_1}" }
146
- reference_mapping.transform_values! { "#{value_key_prefix}.#{_1}" }
145
+ reference_mapping.transform_keys! { "#{(key_prefix + [name]).join("/")}[]/#{_1}" }
146
+ reference_mapping.transform_values! { "#{value_key_prefix}/#{_1}" }
147
147
 
148
148
  mapping.merge!(reference_mapping)
149
149
  else
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Verquest
4
+ module Properties
5
+ # The Const class represents a constant property with a fixed value in a JSON schema.
6
+ # It's used for properties that must have a specific, immutable value.
7
+ #
8
+ # @example
9
+ # const = Const.new(name: "type", value: "user")
10
+ class Const < Base
11
+ # Initialize a new constant property
12
+ #
13
+ # @param name [String, Symbol] The name of the constant property
14
+ # @param value [Object] The fixed value of the constant (can be any scalar value)
15
+ # @param map [Object, nil] Optional mapping information
16
+ # @param required [Boolean, Array<Symbol>] Whether this property is required, or array of dependency names (can be overridden by custom type)
17
+ # @param schema_options [Hash] Additional JSON schema options for this property
18
+ def initialize(name:, value:, map: nil, required: false, **schema_options)
19
+ @name = name.to_s
20
+ @value = value
21
+ @map = map
22
+ @required = required
23
+ @schema_options = schema_options&.transform_keys(&:to_s)
24
+ end
25
+
26
+ # Generate JSON schema definition for this constant
27
+ #
28
+ # @return [Hash] The schema definition for this constant
29
+ def to_schema
30
+ {
31
+ name => {
32
+ "const" => value
33
+ }.merge(schema_options)
34
+ }
35
+ end
36
+
37
+ # Create mapping for this const property
38
+ #
39
+ # @param key_prefix [Array<Symbol>] Prefix for the source key
40
+ # @param value_prefix [Array<String>] Prefix for the target value
41
+ # @param mapping [Hash] The mapping hash to be updated
42
+ # @param version [String, nil] The version to create mapping for
43
+ # @return [Hash] The updated mapping hash
44
+ def mapping(key_prefix:, value_prefix:, mapping:, version: nil)
45
+ mapping[(key_prefix + [name]).join("/")] = mapping_value_key(value_prefix:)
46
+ end
47
+
48
+ private
49
+
50
+ attr_reader :value, :schema_options
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Verquest
4
+ module Properties
5
+ # The Enum class represents a enum property with a list of possible values in a JSON schema.
6
+ #
7
+ # @example
8
+ # enum = Enum.new(name: "type", values: ["member", "admin"])
9
+ class Enum < Base
10
+ # Initialize a new Enum property
11
+ #
12
+ # @param name [String, Symbol] The name of the property
13
+ # @param values [Array] The enum values for this property
14
+ # @param required [Boolean, Array<Symbol>] Whether this property is required, or array of dependency names
15
+ # @param nullable [Boolean] Whether this property can be null
16
+ # @param map [String, nil] The mapping path for this property
17
+ # @param schema_options [Hash] Additional JSON schema options for this property
18
+ # @raise [ArgumentError] If attempting to map an enum to root without a name
19
+ # @raise [ArgumentError] If values is empty
20
+ # @raise [ArgumentError] If values are not unique
21
+ # @raise [ArgumentError] If only one value is provided (should use const instead)
22
+ def initialize(name:, values:, required: false, nullable: false, map: nil, **schema_options)
23
+ raise ArgumentError, "You can not map enums to the root without a name" if map == "/"
24
+ raise ArgumentError, "Values must not be empty" if values.empty?
25
+ raise ArgumentError, "Values must be unique" if values.uniq.length != values.length
26
+ raise ArgumentError, "Use const for a single value" if values.length == 1
27
+
28
+ @name = name.to_s
29
+ @values = values
30
+ @required = required
31
+ @nullable = nullable
32
+ @map = map
33
+ @schema_options = schema_options&.transform_keys(&:to_s)
34
+
35
+ if nullable && !values.include?("null")
36
+ values << "null"
37
+ end
38
+ end
39
+
40
+ # Generate JSON schema definition for this enum
41
+ #
42
+ # @return [Hash] The schema definition for this enum
43
+ def to_schema
44
+ {
45
+ name => {"enum" => values}.merge(schema_options)
46
+ }
47
+ end
48
+
49
+ # Create mapping for this enum property
50
+ #
51
+ # @param key_prefix [Array<Symbol>] Prefix for the source key
52
+ # @param value_prefix [Array<String>] Prefix for the target value
53
+ # @param mapping [Hash] The mapping hash to be updated
54
+ # @param version [String, nil] The version to create mapping for
55
+ # @return [Hash] The updated mapping hash
56
+ def mapping(key_prefix:, value_prefix:, mapping:, version: nil)
57
+ mapping[(key_prefix + [name]).join("/")] = mapping_value_key(value_prefix:)
58
+ end
59
+
60
+ private
61
+
62
+ attr_reader :values, :schema_options
63
+ end
64
+ end
65
+ end
@@ -74,7 +74,7 @@ module Verquest
74
74
  # @param version [String, nil] The version to create mapping for
75
75
  # @return [Hash] The updated mapping hash
76
76
  def mapping(key_prefix:, value_prefix:, mapping:, version: nil)
77
- mapping[(key_prefix + [name]).join(".")] = mapping_value_key(value_prefix:)
77
+ mapping[(key_prefix + [name]).join("/")] = mapping_value_key(value_prefix:)
78
78
  end
79
79
 
80
80
  private
@@ -87,16 +87,16 @@ module Verquest
87
87
  value_key_prefix = mapping_value_key(value_prefix:)
88
88
 
89
89
  # Single field mapping
90
- if property && reference_mapping.size == 1 && !reference_mapping.keys.first.include?(".")
90
+ if property && reference_mapping.size == 1 && !reference_mapping.keys.first.include?("/")
91
91
  reference_mapping = {
92
- (key_prefix + [name]).join(".") => value_key_prefix
92
+ (key_prefix + [name]).join("/") => value_key_prefix
93
93
  }
94
94
  else
95
- if value_key_prefix != "" && !value_key_prefix.end_with?(".")
96
- value_key_prefix = "#{value_key_prefix}."
95
+ if value_key_prefix != "" && !value_key_prefix.end_with?("/")
96
+ value_key_prefix = "#{value_key_prefix}/"
97
97
  end
98
98
 
99
- reference_mapping.transform_keys! { "#{(key_prefix + [name]).join(".")}.#{_1}" }
99
+ reference_mapping.transform_keys! { "#{(key_prefix + [name]).join("/")}/#{_1}" }
100
100
  reference_mapping.transform_values! { "#{value_key_prefix}#{_1}" }
101
101
  end
102
102
 
@@ -3,13 +3,13 @@ module Verquest
3
3
  #
4
4
  # The Transformer class handles the conversion of parameter structures based on
5
5
  # a mapping of source paths to target paths. It supports deep nested structures,
6
- # array notations, and complex path expressions using dot notation.
6
+ # array notations, and complex path expressions using slash notation.
7
7
  #
8
8
  # @example Basic transformation
9
9
  # mapping = {
10
- # "user.firstName" => "user.first_name",
11
- # "user.lastName" => "user.last_name",
12
- # "addresses[].zip" => "addresses[].postal_code"
10
+ # "user/firstName" => "user/first_name",
11
+ # "user/lastName" => "user/last_name",
12
+ # "addresses[]/zip" => "addresses[]/postal_code"
13
13
  # }
14
14
  #
15
15
  # transformer = Verquest::Transformer.new(mapping: mapping)
@@ -84,13 +84,13 @@ module Verquest
84
84
  end
85
85
  end
86
86
 
87
- # Parses a dot-notation path into structured path parts
87
+ # Parses a slash-notation path into structured path parts
88
88
  # Uses memoization for performance optimization
89
89
  #
90
- # @param path [String] The dot-notation path (e.g., "user.address.street")
90
+ # @param path [String] The slash-notation path (e.g., "user/address/street")
91
91
  # @return [Array<Hash>] Array of path parts with :key and :array attributes
92
92
  def parse_path(path)
93
- path_cache[path] ||= path.split(".").map do |part|
93
+ path_cache[path] ||= path.split("/").map do |part|
94
94
  if part.end_with?("[]")
95
95
  {key: part[0...-2], array: true}
96
96
  else
@@ -38,7 +38,10 @@ module Verquest
38
38
  #
39
39
  # @!attribute [r] transformer
40
40
  # @return [Verquest::Transformer] The transformer that applies the mapping
41
- attr_reader :name, :properties, :schema, :validation_schema, :mapping, :transformer
41
+ #
42
+ # @!attribute [r] external_mapping
43
+ # @return [Hash] The mapping from internal attribute paths back to external paths
44
+ attr_reader :name, :properties, :schema, :validation_schema, :mapping, :transformer, :external_mapping
42
45
 
43
46
  # @!attribute [rw] schema_options
44
47
  # @return [Hash] Additional JSON schema options for this version
@@ -113,6 +116,7 @@ module Verquest
113
116
  prepare_schema
114
117
  prepare_validation_schema
115
118
  prepare_mapping
119
+ prepare_external_mapping
116
120
  @transformer = Transformer.new(mapping: mapping)
117
121
 
118
122
  freeze
@@ -245,5 +249,18 @@ module Verquest
245
249
  raise MappingError.new("Mapping must be unique. Found duplicates in version '#{name}': #{duplicates.join(", ")}")
246
250
  end
247
251
  end
252
+
253
+ # Prepares the inverted parameter mapping for this version
254
+ #
255
+ # Inverts the standard mapping to create a reverse lookup from internal
256
+ # attribute names back to external parameter names. This is useful when
257
+ # transforming internal data back to the external API representation.
258
+ #
259
+ # @return [Hash] The frozen inverted mapping where keys are internal attribute
260
+ # paths and values are the corresponding external schema paths
261
+ # @see #prepare_mapping
262
+ def prepare_external_mapping
263
+ @external_mapping = mapping.invert.freeze
264
+ end
248
265
  end
249
266
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: verquest
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Petr Hlavicka
@@ -66,6 +66,8 @@ files:
66
66
  - lib/verquest/properties/array.rb
67
67
  - lib/verquest/properties/base.rb
68
68
  - lib/verquest/properties/collection.rb
69
+ - lib/verquest/properties/const.rb
70
+ - lib/verquest/properties/enum.rb
69
71
  - lib/verquest/properties/field.rb
70
72
  - lib/verquest/properties/object.rb
71
73
  - lib/verquest/properties/reference.rb
@@ -95,7 +97,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
95
97
  - !ruby/object:Gem::Version
96
98
  version: '0'
97
99
  requirements: []
98
- rubygems_version: 3.6.9
100
+ rubygems_version: 3.6.7
99
101
  specification_version: 4
100
102
  summary: Verquest is a Ruby gem that offers an elegant solution for versioning API
101
103
  requests