verquest 0.2.1 → 0.3.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 +4 -4
- data/CHANGELOG.md +8 -0
- data/README.md +88 -82
- data/lib/verquest/base/private_class_methods.rb +1 -1
- data/lib/verquest/base/public_class_methods.rb +6 -5
- data/lib/verquest/configuration.rb +34 -4
- data/lib/verquest/gem_version.rb +1 -1
- data/lib/verquest/properties/array.rb +9 -9
- data/lib/verquest/properties/base.rb +2 -2
- data/lib/verquest/properties/collection.rb +19 -19
- data/lib/verquest/properties/field.rb +8 -8
- data/lib/verquest/properties/object.rb +11 -11
- data/lib/verquest/properties/reference.rb +4 -4
- data/lib/verquest/transformer.rb +5 -6
- data/lib/verquest/version.rb +31 -28
- data/lib/verquest.rb +1 -1
- metadata +5 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0ccc6bfd2d16a987d2ed8ae6c04a9fbfd72a0ed58f00699221193ef76e764cd0
|
4
|
+
data.tar.gz: '0026964f349c5d17f41b18cd7f32431519c46f1530fe92a535488abcd202a86e'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dba0dc768c80d2f51cfb74a9c93483218c8d3f28fffffe01b41d250e78f0d2e504ba64af6ea2dd723de22640170b2151f860424bcdc5ad05b29d24fa694a5081
|
7
|
+
data.tar.gz: 662c43fb095decd144c50afece842467ff96705bbe4a51f27a347a2fdf6041a0bc98895274f280a1441ca88f445a1820d519fc280f9304bc26826f44ea9fcb23
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,13 @@
|
|
1
1
|
## [Unreleased]
|
2
2
|
|
3
|
+
## [0.3.0] - 2025-06-25
|
4
|
+
|
5
|
+
### Breaking Changes
|
6
|
+
- **BREAKING:** Replace `json-schema` gem with `json_schemer` for support of newer JSON Schema specifications (set the lasest by default).
|
7
|
+
- **BREAKING:** Schema and validation schema now uses string keys instead of symbols.
|
8
|
+
|
9
|
+
### Added
|
10
|
+
- Allow insert default values for properties when validation is used.
|
3
11
|
|
4
12
|
## [0.2.1] - 2025-06-22
|
5
13
|
|
data/README.md
CHANGED
@@ -128,49 +128,53 @@ UserCreateRequest.to_schema(version: "2025-06")
|
|
128
128
|
Output:
|
129
129
|
```ruby
|
130
130
|
{
|
131
|
-
type
|
132
|
-
description
|
133
|
-
required
|
134
|
-
properties
|
135
|
-
first_name
|
136
|
-
last_name
|
137
|
-
email
|
138
|
-
birth_date
|
139
|
-
address
|
140
|
-
permissions
|
141
|
-
type
|
142
|
-
items
|
143
|
-
type
|
144
|
-
required
|
145
|
-
properties
|
146
|
-
name
|
147
|
-
read
|
148
|
-
write
|
131
|
+
"type" => "object",
|
132
|
+
"description" => "User Create Request",
|
133
|
+
"required" => ["first_name", "last_name", "email", "address"],
|
134
|
+
"properties" => {
|
135
|
+
"first_name" => {"type" => "string", "description" => "The first name of the user", "maxLength" => 50},
|
136
|
+
"last_name" => {"type" => "string", "description" => "The last name of the user", "maxLength" => 50},
|
137
|
+
"email" => {"type" => "string", "format" => "email", "description" => "The email address of the user"},
|
138
|
+
"birth_date" => {"type" => "string", "format" => "date", "description" => "The birth date of the user"},
|
139
|
+
"address" => {"$ref" => "#/components/schemas/AddressCreateRequest"},
|
140
|
+
"permissions" => {
|
141
|
+
"type" => "array",
|
142
|
+
"items" => {
|
143
|
+
"type" => "object",
|
144
|
+
"required" => ["name"],
|
145
|
+
"properties" => {
|
146
|
+
"name" => {"type" => "string", "description" => "Name of the permission"},
|
147
|
+
"read" => {"type" => "boolean", "description" => "Permission to read"},
|
148
|
+
"write" => {"type" => "boolean", "description" => "Permission to write"}
|
149
149
|
}
|
150
|
-
},
|
151
|
-
description
|
150
|
+
},
|
151
|
+
"description" => "Permissions associated with the user"
|
152
152
|
},
|
153
|
-
role
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
153
|
+
"role" => {
|
154
|
+
"type" => "string",
|
155
|
+
"description" => "Role of the user",
|
156
|
+
"enum" => ["member", "manager"],
|
157
|
+
"default" => "member"
|
158
|
+
},
|
159
|
+
"profile_details" => {
|
160
|
+
"type" => "object",
|
161
|
+
"required" => [],
|
162
|
+
"properties" => {
|
163
|
+
"bio" => {"type" => "string", "description" => "Short biography of the user"},
|
164
|
+
"hobbies" => {"type" => "array", "items" => {"type" => "string"}, "description" => "Tags associated with the user"},
|
165
|
+
"social_links" => {
|
166
|
+
"type" => "object",
|
167
|
+
"required" => [],
|
168
|
+
"properties" => {
|
169
|
+
"github" => {"type" => "string", "format" => "uri", "description" => "GitHub profile URL"},
|
170
|
+
"mastodon" => {"type" => "string", "format" => "uri", "description" => "Mastodon profile URL"}
|
171
|
+
},
|
172
|
+
"description" => "Some social networks"
|
168
173
|
}
|
169
174
|
}
|
170
175
|
}
|
171
176
|
},
|
172
|
-
additionalProperties
|
173
|
-
}
|
177
|
+
"additionalProperties" => false}
|
174
178
|
```
|
175
179
|
|
176
180
|
### JSON schema for validation
|
@@ -184,59 +188,61 @@ UserCreateRequest.to_validation_schema(version: "2025-06")
|
|
184
188
|
Output:
|
185
189
|
```ruby
|
186
190
|
{
|
187
|
-
type
|
188
|
-
description
|
189
|
-
required
|
190
|
-
properties
|
191
|
-
first_name
|
192
|
-
last_name
|
193
|
-
email
|
194
|
-
birth_date
|
195
|
-
address
|
196
|
-
type
|
197
|
-
description
|
198
|
-
required
|
199
|
-
properties
|
200
|
-
street
|
201
|
-
city
|
202
|
-
postal_code
|
203
|
-
country
|
191
|
+
"type" => "object",
|
192
|
+
"description" => "User Create Request",
|
193
|
+
"required" => ["first_name", "last_name", "email", "address"],
|
194
|
+
"properties" => {
|
195
|
+
"first_name" => {"type" => "string", "description" => "The first name of the user", "maxLength" => 50},
|
196
|
+
"last_name" => {"type" => "string", "description" => "The last name of the user", "maxLength" => 50},
|
197
|
+
"email" => {"type" => "string", "format" => "email", "description" => "The email address of the user"},
|
198
|
+
"birth_date" => {"type" => "string", "format" => "date", "description" => "The birth date of the user"},
|
199
|
+
"address" => { # from the AddressCreateRequest
|
200
|
+
"type" => "object",
|
201
|
+
"description" => "Address Create Request",
|
202
|
+
"required" => ["street", "city", "postal_code", "country"],
|
203
|
+
"properties" => {
|
204
|
+
"street" => {"type" => "string", "description" => "Street address"},
|
205
|
+
"city" => {"type" => "string", "description" => "City of residence"},
|
206
|
+
"postal_code" => {"type" => "string", "description" => "Postal code"},
|
207
|
+
"country" => {"type" => "string", "description" => "Country of residence"}
|
204
208
|
},
|
205
|
-
additionalProperties
|
209
|
+
"additionalProperties" => false
|
206
210
|
},
|
207
|
-
permissions
|
208
|
-
type
|
209
|
-
items
|
210
|
-
type
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
write: {type: :boolean, description: "Permission to write"}
|
211
|
+
"permissions" => {
|
212
|
+
"type" => "array",
|
213
|
+
"items" => {
|
214
|
+
"type" => "object", "required" => ["name"],
|
215
|
+
"properties" => {
|
216
|
+
"name" => {"type" => "string", "description" => "Name of the permission"},
|
217
|
+
"read" => {"type" => "boolean", "description" => "Permission to read"},
|
218
|
+
"write" => {"type" => "boolean", "description" => "Permission to write"}
|
216
219
|
}
|
217
220
|
},
|
218
|
-
description
|
221
|
+
"description" => "Permissions associated with the user"
|
219
222
|
},
|
220
|
-
role
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
223
|
+
"role" => {
|
224
|
+
"type" => "string",
|
225
|
+
"description" => "Role of the user",
|
226
|
+
"enum" => ["member", "manager"],
|
227
|
+
"default" => "member"
|
228
|
+
},
|
229
|
+
"profile_details" => {"type" => "object",
|
230
|
+
"required" => [],
|
231
|
+
"properties" => {
|
232
|
+
"bio" => {"type" => "string", "description" => "Short biography of the user"},
|
233
|
+
"hobbies" => {"type" => "array", "items" => {"type" => "string"}, "description" => "Tags associated with the user"},
|
234
|
+
"social_links" => {
|
235
|
+
"type" => "object",
|
236
|
+
"required" => [],
|
237
|
+
"properties" => {
|
238
|
+
"github" => {"type" => "string", "format" => "uri", "description" => "GitHub profile URL"},
|
239
|
+
"mastodon" => {"type" => "string", "format" => "uri", "description" => "Mastodon profile URL"}
|
240
|
+
},
|
241
|
+
"description" => "Some social networks"}
|
236
242
|
}
|
237
243
|
}
|
238
244
|
},
|
239
|
-
additionalProperties
|
245
|
+
"additionalProperties" => false
|
240
246
|
}
|
241
247
|
```
|
242
248
|
|
@@ -64,7 +64,7 @@ module Verquest
|
|
64
64
|
instance_exec(&block)
|
65
65
|
ensure
|
66
66
|
version.description ||= versions.description
|
67
|
-
version.schema_options = versions.schema_options.merge(version.schema_options)
|
67
|
+
version.schema_options = versions.schema_options.merge(version.schema_options).transform_keys(&:to_s)
|
68
68
|
version.prepare
|
69
69
|
end
|
70
70
|
|
@@ -12,7 +12,8 @@ module Verquest
|
|
12
12
|
# @param version [String, nil] Specific version to use, defaults to configuration setting
|
13
13
|
# @param validate [Boolean, nil] Whether to validate the params, defaults to configuration setting
|
14
14
|
# @param remove_extra_root_keys [Boolean, nil] Whether to remove extra keys at the root level, defaults to configuration setting
|
15
|
-
# @return [Verquest::Result] Success result with mapped params or
|
15
|
+
# @return [Verquest::Result, Hash, Exception] When validation_error_handling is :result, returns a Success result with mapped params or Failure result with validation errors.
|
16
|
+
# When validation_error_handling is :raise, returns mapped params directly or raises InvalidParamsError with validation errors.
|
16
17
|
def process(params, version: nil, validate: nil, remove_extra_root_keys: nil)
|
17
18
|
validate = Verquest.configuration.validate_params if validate.nil?
|
18
19
|
remove_extra_root_keys = Verquest.configuration.remove_extra_root_keys if remove_extra_root_keys.nil?
|
@@ -23,7 +24,7 @@ module Verquest
|
|
23
24
|
params = params.to_unsafe_h if params.respond_to?(:to_unsafe_h)
|
24
25
|
params = params.slice(*version_class.properties.keys) if remove_extra_root_keys
|
25
26
|
|
26
|
-
if validate && (validation_result = version_class.validate_params(params: params
|
27
|
+
if validate && (validation_result = version_class.validate_params(params: params)) && validation_result.any?
|
27
28
|
case Verquest.configuration.validation_error_handling
|
28
29
|
when :raise
|
29
30
|
raise InvalidParamsError.new("Validation failed", errors: validation_result)
|
@@ -59,7 +60,7 @@ module Verquest
|
|
59
60
|
version = resolve(version)
|
60
61
|
|
61
62
|
if property
|
62
|
-
version.validation_schema[
|
63
|
+
version.validation_schema["properties"][property.to_s]
|
63
64
|
else
|
64
65
|
version.validation_schema
|
65
66
|
end
|
@@ -76,7 +77,7 @@ module Verquest
|
|
76
77
|
# Returns the mapping for a specific version or property
|
77
78
|
#
|
78
79
|
# @param version [String, nil] Specific version to use, defaults to configuration setting
|
79
|
-
# @param property [Symbol, nil] Specific property to retrieve mapping for
|
80
|
+
# @param property [String, Symbol, nil] Specific property to retrieve mapping for
|
80
81
|
# @return [Hash] The mapping configuration
|
81
82
|
def mapping(version: nil, property: nil)
|
82
83
|
version = resolve(version)
|
@@ -90,7 +91,7 @@ module Verquest
|
|
90
91
|
|
91
92
|
# Returns the JSON reference for the request or a specific property
|
92
93
|
#
|
93
|
-
# @param property [Symbol, nil] Specific property to retrieve reference for
|
94
|
+
# @param property [String, Symbol, nil] Specific property to retrieve reference for
|
94
95
|
# @return [String] The JSON reference for the request or property
|
95
96
|
def to_ref(property: nil)
|
96
97
|
base = "#/components/schemas/#{component_name}"
|
@@ -11,13 +11,23 @@ module Verquest
|
|
11
11
|
# config.current_version = -> { Current.api_version }
|
12
12
|
# end
|
13
13
|
class Configuration
|
14
|
+
SCHEMAS = {
|
15
|
+
draft4: JSONSchemer::Draft4,
|
16
|
+
draft6: JSONSchemer::Draft6,
|
17
|
+
draft7: JSONSchemer::Draft7,
|
18
|
+
draft2019_09: JSONSchemer::Draft201909,
|
19
|
+
draft2020_12: JSONSchemer::Draft202012,
|
20
|
+
openapi30: JSONSchemer::OpenAPI30,
|
21
|
+
openapi31: JSONSchemer::OpenAPI31
|
22
|
+
}.freeze
|
23
|
+
|
14
24
|
# @!attribute [rw] validate_params
|
15
25
|
# Controls whether parameters are automatically validated against the schema
|
16
26
|
# @return [Boolean] true if validation is enabled, false otherwise
|
17
27
|
#
|
18
28
|
# @!attribute [rw] json_schema_version
|
19
|
-
# The JSON Schema draft version to use for validation and schema generation (see
|
20
|
-
# @return [Symbol] The JSON Schema version (e.g., :
|
29
|
+
# The JSON Schema draft version to use for validation and schema generation (see Configuration::SCHEMAS)
|
30
|
+
# @return [Symbol] The JSON Schema version (e.g., :draft2020_12, :draft2019_09, :draft7)
|
21
31
|
#
|
22
32
|
# @!attribute [rw] validation_error_handling
|
23
33
|
# Controls how errors during parameter processing are handled
|
@@ -26,7 +36,11 @@ module Verquest
|
|
26
36
|
# @!attribute [rw] remove_extra_root_keys
|
27
37
|
# Controls if extra root keys not defined in the schema should be removed from the parameters
|
28
38
|
# @return [Boolean] true if extra keys should be removed, false otherwise
|
29
|
-
|
39
|
+
#
|
40
|
+
# @!attribute [rw] insert_property_defaults
|
41
|
+
# Controls whether default values defined in property schemas should be inserted when not provided during validation
|
42
|
+
# @return [Boolean] true if default values should be inserted, false otherwise
|
43
|
+
attr_accessor :validate_params, :json_schema_version, :validation_error_handling, :remove_extra_root_keys, :insert_property_defaults
|
30
44
|
|
31
45
|
# @!attribute [r] current_version
|
32
46
|
# A callable object that returns the current API version to use when not explicitly specified
|
@@ -42,10 +56,11 @@ module Verquest
|
|
42
56
|
# @return [Configuration] A new configuration instance with default settings
|
43
57
|
def initialize
|
44
58
|
@validate_params = true
|
45
|
-
@json_schema_version = :
|
59
|
+
@json_schema_version = :draft2020_12
|
46
60
|
@validation_error_handling = :raise # or :result
|
47
61
|
@remove_extra_root_keys = true
|
48
62
|
@version_resolver = VersionResolver
|
63
|
+
@insert_property_defaults = true
|
49
64
|
end
|
50
65
|
|
51
66
|
# Sets the current version strategy using a callable object
|
@@ -69,5 +84,20 @@ module Verquest
|
|
69
84
|
|
70
85
|
@version_resolver = version_resolver
|
71
86
|
end
|
87
|
+
|
88
|
+
# Gets the JSON Schema class based on the configured version
|
89
|
+
#
|
90
|
+
# @return [Class] The JSON Schema class matching the configured version
|
91
|
+
# @raise [ArgumentError] If the configured json_schema_version is not supported
|
92
|
+
def json_schema
|
93
|
+
SCHEMAS[json_schema_version] || raise(ArgumentError, "Unsupported JSON Schema version: #{json_schema_version}")
|
94
|
+
end
|
95
|
+
|
96
|
+
# Gets the JSON Schema URI for the configured schema version
|
97
|
+
#
|
98
|
+
# @return [String] The base URI for the configured JSON Schema version
|
99
|
+
def json_schema_uri
|
100
|
+
json_schema::BASE_URI.to_s
|
101
|
+
end
|
72
102
|
end
|
73
103
|
end
|
data/lib/verquest/gem_version.rb
CHANGED
@@ -16,8 +16,8 @@ module Verquest
|
|
16
16
|
class Array < Base
|
17
17
|
# Initialize a new Array property
|
18
18
|
#
|
19
|
-
# @param name [Symbol] The name of the property
|
20
|
-
# @param type [Symbol] The type of items in the array
|
19
|
+
# @param name [String, Symbol] The name of the property
|
20
|
+
# @param type [String, Symbol] The type of items in the array
|
21
21
|
# @param map [String, nil] The mapping path for this property (nil for no explicit mapping)
|
22
22
|
# @param required [Boolean] Whether this property is required
|
23
23
|
# @param schema_options [Hash] Additional JSON schema options for this property
|
@@ -25,11 +25,11 @@ module Verquest
|
|
25
25
|
def initialize(name:, type:, map: nil, required: false, **schema_options)
|
26
26
|
raise ArgumentError, "You can not map array to the root" if map == "/"
|
27
27
|
|
28
|
-
@name = name
|
29
|
-
@type = type
|
28
|
+
@name = name.to_s
|
29
|
+
@type = type.to_s
|
30
30
|
@map = map
|
31
31
|
@required = required
|
32
|
-
@schema_options = schema_options
|
32
|
+
@schema_options = schema_options&.transform_keys(&:to_s)
|
33
33
|
end
|
34
34
|
|
35
35
|
# Generate JSON schema definition for this array property
|
@@ -38,16 +38,16 @@ module Verquest
|
|
38
38
|
def to_schema
|
39
39
|
{
|
40
40
|
name => {
|
41
|
-
type
|
42
|
-
items
|
41
|
+
"type" => "array",
|
42
|
+
"items" => {"type" => type}
|
43
43
|
}.merge(schema_options)
|
44
44
|
}
|
45
45
|
end
|
46
46
|
|
47
47
|
# Create mapping for this array property
|
48
48
|
#
|
49
|
-
# @param key_prefix [Array<
|
50
|
-
# @param value_prefix [Array<
|
49
|
+
# @param key_prefix [Array<String>] Prefix for the source key
|
50
|
+
# @param value_prefix [Array<String>] Prefix for the target value
|
51
51
|
# @param mapping [Hash] The mapping hash to be updated
|
52
52
|
# @param version [String, nil] The version to create mapping for, defaults to configuration setting
|
53
53
|
# @return [Hash] The updated mapping hash
|
@@ -11,7 +11,7 @@ module Verquest
|
|
11
11
|
# @abstract Subclass and override {#to_schema}, {#mapping} to implement
|
12
12
|
class Base
|
13
13
|
# @!attribute [rw] name
|
14
|
-
# @return [
|
14
|
+
# @return [String] The name of the property
|
15
15
|
# @!attribute [rw] required
|
16
16
|
# @return [Boolean] Whether this property is required
|
17
17
|
# @!attribute [rw] map
|
@@ -43,7 +43,7 @@ module Verquest
|
|
43
43
|
|
44
44
|
# Creates mapping for this property
|
45
45
|
# @abstract
|
46
|
-
# @param key_prefix [Array<
|
46
|
+
# @param key_prefix [Array<String>] Prefix for the source key
|
47
47
|
# @param value_prefix [Array<String>] Prefix for the target value
|
48
48
|
# @param mapping [Hash] The mapping hash to be updated
|
49
49
|
# @param version [String, nil] The version to create mapping for
|
@@ -20,7 +20,7 @@ module Verquest
|
|
20
20
|
class Collection < Base
|
21
21
|
# Initialize a new Collection property
|
22
22
|
#
|
23
|
-
# @param name [Symbol] The name of the property
|
23
|
+
# @param name [String, Symbol] The name of the property
|
24
24
|
# @param item [Verquest::Base, nil] Optional reference to an external schema class
|
25
25
|
# @param required [Boolean] Whether this property is required
|
26
26
|
# @param map [String, nil] The mapping path for this property
|
@@ -31,11 +31,11 @@ module Verquest
|
|
31
31
|
|
32
32
|
@properties = {}
|
33
33
|
|
34
|
-
@name = name
|
34
|
+
@name = name.to_s
|
35
35
|
@item = item
|
36
36
|
@required = required
|
37
37
|
@map = map
|
38
|
-
@schema_options = schema_options
|
38
|
+
@schema_options = schema_options&.transform_keys(&:to_s)
|
39
39
|
end
|
40
40
|
|
41
41
|
# Add a child property to this collection's item definition
|
@@ -60,20 +60,20 @@ module Verquest
|
|
60
60
|
if has_item?
|
61
61
|
{
|
62
62
|
name => {
|
63
|
-
type
|
64
|
-
items
|
65
|
-
"$ref"
|
63
|
+
"type" => "array",
|
64
|
+
"items" => {
|
65
|
+
"$ref" => item.to_ref
|
66
66
|
}
|
67
67
|
}.merge(schema_options)
|
68
68
|
}
|
69
69
|
else
|
70
70
|
{
|
71
71
|
name => {
|
72
|
-
type
|
73
|
-
items
|
74
|
-
type
|
75
|
-
required
|
76
|
-
properties
|
72
|
+
"type" => "array",
|
73
|
+
"items" => {
|
74
|
+
"type" => "object",
|
75
|
+
"required" => properties.values.select(&:required).map(&:name),
|
76
|
+
"properties" => properties.transform_values { |property| property.to_schema[property.name] }
|
77
77
|
}
|
78
78
|
}.merge(schema_options)
|
79
79
|
}
|
@@ -88,18 +88,18 @@ module Verquest
|
|
88
88
|
if has_item?
|
89
89
|
{
|
90
90
|
name => {
|
91
|
-
type
|
92
|
-
items
|
91
|
+
"type" => "array",
|
92
|
+
"items" => item.to_validation_schema(version: version)
|
93
93
|
}.merge(schema_options)
|
94
94
|
}
|
95
95
|
else
|
96
96
|
{
|
97
97
|
name => {
|
98
|
-
type
|
99
|
-
items
|
100
|
-
type
|
101
|
-
required
|
102
|
-
properties
|
98
|
+
"type" => "array",
|
99
|
+
"items" => {
|
100
|
+
"type" => "object",
|
101
|
+
"required" => properties.values.select(&:required).map(&:name),
|
102
|
+
"properties" => properties.transform_values { |property| property.to_validation_schema(version: version)[property.name] }
|
103
103
|
}
|
104
104
|
}.merge(schema_options)
|
105
105
|
}
|
@@ -118,7 +118,7 @@ module Verquest
|
|
118
118
|
# - Creates mappings for each property in the collection items
|
119
119
|
# - Each property gets mapped with array notation and appropriate prefixes
|
120
120
|
#
|
121
|
-
# @param key_prefix [Array<
|
121
|
+
# @param key_prefix [Array<String>] Prefix for the source key
|
122
122
|
# @param value_prefix [Array<String>] Prefix for the target value
|
123
123
|
# @param mapping [Hash] The mapping hash to be updated
|
124
124
|
# @param version [String, nil] The version to create mapping for
|
@@ -17,33 +17,33 @@ module Verquest
|
|
17
17
|
class Field < Base
|
18
18
|
# List of allowed field types
|
19
19
|
# @return [Array<Symbol>]
|
20
|
-
ALLOWED_TYPES = %
|
20
|
+
ALLOWED_TYPES = %w[string number integer boolean].freeze
|
21
21
|
|
22
22
|
# Initialize a new Field property
|
23
23
|
#
|
24
|
-
# @param name [Symbol] The name of the property
|
25
|
-
# @param type [Symbol] The data type for this field, must be one of ALLOWED_TYPES
|
24
|
+
# @param name [String, Symbol] The name of the property
|
25
|
+
# @param type [String, Symbol] The data type for this field, must be one of ALLOWED_TYPES
|
26
26
|
# @param required [Boolean] Whether this property is required
|
27
27
|
# @param map [String, nil] The mapping path for this property
|
28
28
|
# @param schema_options [Hash] Additional JSON schema options for this property
|
29
29
|
# @raise [ArgumentError] If type is not one of the allowed types
|
30
30
|
# @raise [ArgumentError] If attempting to map a field to root without a name
|
31
31
|
def initialize(name:, type:, required: false, map: nil, **schema_options)
|
32
|
-
raise ArgumentError, "Type must be one of #{ALLOWED_TYPES.join(", ")}" unless ALLOWED_TYPES.include?(type)
|
32
|
+
raise ArgumentError, "Type must be one of #{ALLOWED_TYPES.join(", ")}" unless ALLOWED_TYPES.include?(type.to_s)
|
33
33
|
raise ArgumentError, "You can not map fields to the root without a name" if map == "/"
|
34
34
|
|
35
|
-
@name = name
|
36
|
-
@type = type
|
35
|
+
@name = name.to_s
|
36
|
+
@type = type.to_s
|
37
37
|
@required = required
|
38
38
|
@map = map
|
39
|
-
@schema_options = schema_options
|
39
|
+
@schema_options = schema_options&.transform_keys(&:to_s)
|
40
40
|
end
|
41
41
|
|
42
42
|
# Generate JSON schema definition for this field
|
43
43
|
#
|
44
44
|
# @return [Hash] The schema definition for this field
|
45
45
|
def to_schema
|
46
|
-
{name => {type
|
46
|
+
{name => {"type" => type}.merge(schema_options)}
|
47
47
|
end
|
48
48
|
|
49
49
|
# Create mapping for this field property
|
@@ -14,17 +14,17 @@ module Verquest
|
|
14
14
|
class Object < Base
|
15
15
|
# Initialize a new Object property
|
16
16
|
#
|
17
|
-
# @param name [String] The name of the property
|
17
|
+
# @param name [String, Symbol] The name of the property
|
18
18
|
# @param required [Boolean] Whether this property is required
|
19
19
|
# @param map [String, nil] The mapping path for this property
|
20
20
|
# @param schema_options [Hash] Additional JSON schema options for this property
|
21
21
|
def initialize(name:, required: false, map: nil, **schema_options)
|
22
22
|
@properties = {}
|
23
23
|
|
24
|
-
@name = name
|
24
|
+
@name = name.to_s
|
25
25
|
@required = required
|
26
26
|
@map = map
|
27
|
-
@schema_options = schema_options
|
27
|
+
@schema_options = schema_options&.transform_keys(&:to_s)
|
28
28
|
end
|
29
29
|
|
30
30
|
# Add a child property to this object
|
@@ -32,7 +32,7 @@ module Verquest
|
|
32
32
|
# @param property [Verquest::Properties::Base] The property to add to this object
|
33
33
|
# @return [Verquest::Properties::Base] The added property
|
34
34
|
def add(property)
|
35
|
-
properties[property.name] = property
|
35
|
+
properties[property.name.to_s] = property
|
36
36
|
end
|
37
37
|
|
38
38
|
# Generate JSON schema definition for this object property
|
@@ -41,9 +41,9 @@ module Verquest
|
|
41
41
|
def to_schema
|
42
42
|
{
|
43
43
|
name => {
|
44
|
-
type
|
45
|
-
required
|
46
|
-
properties
|
44
|
+
"type" => "object",
|
45
|
+
"required" => properties.values.select(&:required).map(&:name),
|
46
|
+
"properties" => properties.transform_values { |property| property.to_schema[property.name] }
|
47
47
|
}.merge(schema_options)
|
48
48
|
}
|
49
49
|
end
|
@@ -55,16 +55,16 @@ module Verquest
|
|
55
55
|
def to_validation_schema(version: nil)
|
56
56
|
{
|
57
57
|
name => {
|
58
|
-
type
|
59
|
-
required
|
60
|
-
properties
|
58
|
+
"type" => "object",
|
59
|
+
"required" => properties.values.select(&:required).map(&:name),
|
60
|
+
"properties" => properties.transform_values { |property| property.to_validation_schema(version: version)[property.name] }
|
61
61
|
}.merge(schema_options)
|
62
62
|
}
|
63
63
|
end
|
64
64
|
|
65
65
|
# Create mapping for this object property and all its children
|
66
66
|
#
|
67
|
-
# @param key_prefix [Array<
|
67
|
+
# @param key_prefix [Array<String>] Prefix for the source key
|
68
68
|
# @param value_prefix [Array<String>] Prefix for the target value
|
69
69
|
# @param mapping [Hash] The mapping hash to be updated
|
70
70
|
# @param version [String, nil] The version to create mapping for
|
@@ -23,13 +23,13 @@ module Verquest
|
|
23
23
|
class Reference < Base
|
24
24
|
# Initialize a new Reference property
|
25
25
|
#
|
26
|
-
# @param name [String] The name of the property
|
26
|
+
# @param name [String, Symbol] The name of the property
|
27
27
|
# @param from [Class] The schema class to reference
|
28
28
|
# @param property [Symbol, nil] Optional specific property to reference
|
29
29
|
# @param map [String, nil] The mapping path for this property
|
30
30
|
# @param required [Boolean] Whether this property is required
|
31
31
|
def initialize(name:, from:, property: nil, map: nil, required: false)
|
32
|
-
@name = name
|
32
|
+
@name = name.to_s
|
33
33
|
@from = from
|
34
34
|
@property = property
|
35
35
|
@map = map
|
@@ -41,7 +41,7 @@ module Verquest
|
|
41
41
|
# @return [Hash] The schema definition with a $ref pointer
|
42
42
|
def to_schema
|
43
43
|
{
|
44
|
-
name => {"$ref"
|
44
|
+
name => {"$ref" => from.to_ref(property: property)}
|
45
45
|
}
|
46
46
|
end
|
47
47
|
|
@@ -58,7 +58,7 @@ module Verquest
|
|
58
58
|
# Create mapping for this reference property
|
59
59
|
# This delegates to the referenced schema's mapping with appropriate key prefixing
|
60
60
|
#
|
61
|
-
# @param key_prefix [Array<
|
61
|
+
# @param key_prefix [Array<String>] Prefix for the source key
|
62
62
|
# @param value_prefix [Array<String>] Prefix for the target value
|
63
63
|
# @param mapping [Hash] The mapping hash to be updated
|
64
64
|
# @param version [String, nil] The version to create mapping for
|
data/lib/verquest/transformer.rb
CHANGED
@@ -113,12 +113,11 @@ module Verquest
|
|
113
113
|
|
114
114
|
case data
|
115
115
|
when Hash
|
116
|
-
#
|
117
|
-
return nil unless data.key?(key.to_s)
|
116
|
+
# Only check for string keys
|
117
|
+
return nil unless data.key?(key.to_s)
|
118
118
|
|
119
|
-
#
|
120
|
-
|
121
|
-
value = data[actual_key]
|
119
|
+
# Always use string keys
|
120
|
+
value = data[key.to_s]
|
122
121
|
|
123
122
|
if current_part[:array] && value.is_a?(Array)
|
124
123
|
# Process array elements and filter out nil values
|
@@ -153,7 +152,7 @@ module Verquest
|
|
153
152
|
|
154
153
|
current_part = path_parts.first
|
155
154
|
remaining_path = path_parts[1..]
|
156
|
-
key = current_part[:key].
|
155
|
+
key = current_part[:key].to_s # Ensure key is a string for consistency
|
157
156
|
|
158
157
|
if remaining_path.empty?
|
159
158
|
# End of path, set the value directly
|
data/lib/verquest/version.rb
CHANGED
@@ -50,7 +50,7 @@ module Verquest
|
|
50
50
|
# @param name [String] The name/identifier of the version
|
51
51
|
# @return [Version] A new Version instance
|
52
52
|
def initialize(name:)
|
53
|
-
@name = name
|
53
|
+
@name = name.to_s
|
54
54
|
@schema_options = {}
|
55
55
|
@properties = {}
|
56
56
|
end
|
@@ -69,7 +69,7 @@ module Verquest
|
|
69
69
|
# @return [Verquest::Properties::Base] The removed property
|
70
70
|
# @raise [PropertyNotFoundError] If the property doesn't exist
|
71
71
|
def remove(property_name)
|
72
|
-
properties.delete(property_name) || raise(PropertyNotFoundError.new("Property '#{property_name}' is not defined on '#{name}"))
|
72
|
+
properties.delete(property_name.to_s) || raise(PropertyNotFoundError.new("Property '#{property_name}' is not defined on '#{name}'"))
|
73
73
|
end
|
74
74
|
|
75
75
|
# Check if this version has a property with the given name
|
@@ -77,7 +77,7 @@ module Verquest
|
|
77
77
|
# @param property_name [Symbol, String] The name of the property to check
|
78
78
|
# @return [Boolean] true if the property exists, false otherwise
|
79
79
|
def has?(property_name)
|
80
|
-
properties.key?(property_name)
|
80
|
+
properties.key?(property_name.to_s)
|
81
81
|
end
|
82
82
|
|
83
83
|
# Copy properties from another version
|
@@ -90,7 +90,7 @@ module Verquest
|
|
90
90
|
raise ArgumentError, "Expected a Verquest::Version instance" unless version.is_a?(Version)
|
91
91
|
|
92
92
|
version.properties.values.each do |property|
|
93
|
-
next if exclude_properties.include?(property.name)
|
93
|
+
next if exclude_properties.include?(property.name.to_sym)
|
94
94
|
|
95
95
|
add(property)
|
96
96
|
end
|
@@ -114,27 +114,30 @@ module Verquest
|
|
114
114
|
#
|
115
115
|
# @return [Boolean] true if the schema is valid, false otherwise
|
116
116
|
def validate_schema
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
117
|
+
JSONSchemer.validate_schema(
|
118
|
+
validation_schema,
|
119
|
+
meta_schema: Verquest.configuration.json_schema_uri
|
120
|
+
)
|
121
121
|
end
|
122
122
|
|
123
123
|
# Validate request parameters against the version's validation schema
|
124
124
|
#
|
125
125
|
# @param params [Hash] The request parameters to validate
|
126
|
-
# @param component_reference [String] A reference string for components in the schema
|
127
|
-
# @param remove_extra_root_keys [Boolean] Whether to remove extra keys not in the schema
|
128
126
|
# @return [Array<Hash>] An array of validation error details, or empty if valid
|
129
|
-
def validate_params(params
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
127
|
+
def validate_params(params:)
|
128
|
+
schemer = JSONSchemer.schema(
|
129
|
+
validation_schema,
|
130
|
+
meta_schema: Verquest.configuration.json_schema_uri,
|
131
|
+
insert_property_defaults: Verquest.configuration.insert_property_defaults
|
132
|
+
)
|
133
|
+
|
134
|
+
schemer.validate(params).map do |error|
|
135
|
+
{
|
136
|
+
pointer: error["data_pointer"],
|
137
|
+
type: error["type"],
|
138
|
+
message: error["error"],
|
139
|
+
details: error["details"]
|
140
|
+
}
|
138
141
|
end
|
139
142
|
end
|
140
143
|
|
@@ -147,7 +150,7 @@ module Verquest
|
|
147
150
|
raise PropertyNotFoundError.new("Property '#{property}' is not defined on '#{name}'") unless has?(property)
|
148
151
|
|
149
152
|
{}.tap do |mapping|
|
150
|
-
properties[property].mapping(key_prefix: [], value_prefix: [], mapping: mapping, version: name)
|
153
|
+
properties[property.to_s].mapping(key_prefix: [], value_prefix: [], mapping: mapping, version: name)
|
151
154
|
end
|
152
155
|
end
|
153
156
|
|
@@ -170,10 +173,10 @@ module Verquest
|
|
170
173
|
# @return [Hash] The frozen schema hash
|
171
174
|
def prepare_schema
|
172
175
|
@schema = {
|
173
|
-
type
|
174
|
-
description
|
175
|
-
required
|
176
|
-
properties
|
176
|
+
"type" => "object",
|
177
|
+
"description" => description,
|
178
|
+
"required" => properties.values.select(&:required).map(&:name),
|
179
|
+
"properties" => properties.transform_values { |property| property.to_schema[property.name] }
|
177
180
|
}.merge(schema_options).freeze
|
178
181
|
end
|
179
182
|
|
@@ -185,10 +188,10 @@ module Verquest
|
|
185
188
|
# @return [Hash] The frozen validation schema hash
|
186
189
|
def prepare_validation_schema
|
187
190
|
@validation_schema = {
|
188
|
-
type
|
189
|
-
description
|
190
|
-
required
|
191
|
-
properties
|
191
|
+
"type" => "object",
|
192
|
+
"description" => description,
|
193
|
+
"required" => properties.values.select(&:required).map(&:name),
|
194
|
+
"properties" => properties.transform_values { |property| property.to_validation_schema(version: name)[property.name] }
|
192
195
|
}.merge(schema_options).freeze
|
193
196
|
end
|
194
197
|
|
data/lib/verquest.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: verquest
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Petr Hlavicka
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-06-
|
11
|
+
date: 2025-06-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: zeitwerk
|
@@ -25,19 +25,19 @@ dependencies:
|
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '2.7'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
28
|
+
name: json_schemer
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
33
|
+
version: '2.4'
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '
|
40
|
+
version: '2.4'
|
41
41
|
description: Verquest helps you version API requests, simplifying the management of
|
42
42
|
changes, handling the mapping for internal versus external names and structures,
|
43
43
|
validating parameters, and exporting your requests to JSON Schema components for
|