apiwork 0.0.0.pre → 0.1.2
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/LICENSE.txt +2 -2
- data/README.md +117 -1
- data/Rakefile +5 -3
- data/app/controllers/apiwork/errors_controller.rb +13 -0
- data/app/controllers/apiwork/exports_controller.rb +22 -0
- data/lib/apiwork/abstractable.rb +26 -0
- data/lib/apiwork/adapter/base.rb +369 -0
- data/lib/apiwork/adapter/builder/api/base.rb +66 -0
- data/lib/apiwork/adapter/builder/contract/base.rb +86 -0
- data/lib/apiwork/adapter/capability/api/base.rb +51 -0
- data/lib/apiwork/adapter/capability/api/scope.rb +64 -0
- data/lib/apiwork/adapter/capability/base.rb +291 -0
- data/lib/apiwork/adapter/capability/contract/base.rb +37 -0
- data/lib/apiwork/adapter/capability/contract/scope.rb +110 -0
- data/lib/apiwork/adapter/capability/operation/base.rb +172 -0
- data/lib/apiwork/adapter/capability/operation/metadata_shape.rb +165 -0
- data/lib/apiwork/adapter/capability/result.rb +21 -0
- data/lib/apiwork/adapter/capability/runner.rb +56 -0
- data/lib/apiwork/adapter/capability/transformer/request/base.rb +72 -0
- data/lib/apiwork/adapter/capability/transformer/response/base.rb +45 -0
- data/lib/apiwork/adapter/registry.rb +16 -0
- data/lib/apiwork/adapter/serializer/error/base.rb +72 -0
- data/lib/apiwork/adapter/serializer/error/default/api_builder.rb +32 -0
- data/lib/apiwork/adapter/serializer/error/default.rb +37 -0
- data/lib/apiwork/adapter/serializer/resource/base.rb +84 -0
- data/lib/apiwork/adapter/serializer/resource/default/contract_builder.rb +209 -0
- data/lib/apiwork/adapter/serializer/resource/default.rb +39 -0
- data/lib/apiwork/adapter/standard/capability/filtering/api_builder.rb +75 -0
- data/lib/apiwork/adapter/standard/capability/filtering/constants.rb +37 -0
- data/lib/apiwork/adapter/standard/capability/filtering/contract_builder.rb +193 -0
- data/lib/apiwork/adapter/standard/capability/filtering/operation/filter/builder.rb +47 -0
- data/lib/apiwork/adapter/standard/capability/filtering/operation/filter/operator_builder.rb +36 -0
- data/lib/apiwork/adapter/standard/capability/filtering/operation/filter.rb +462 -0
- data/lib/apiwork/adapter/standard/capability/filtering/operation.rb +22 -0
- data/lib/apiwork/adapter/standard/capability/filtering/request_transformer.rb +47 -0
- data/lib/apiwork/adapter/standard/capability/filtering.rb +18 -0
- data/lib/apiwork/adapter/standard/capability/including/contract_builder.rb +169 -0
- data/lib/apiwork/adapter/standard/capability/including/operation.rb +20 -0
- data/lib/apiwork/adapter/standard/capability/including.rb +16 -0
- data/lib/apiwork/adapter/standard/capability/pagination/api_builder.rb +34 -0
- data/lib/apiwork/adapter/standard/capability/pagination/contract_builder.rb +35 -0
- data/lib/apiwork/adapter/standard/capability/pagination/operation/paginate/cursor.rb +84 -0
- data/lib/apiwork/adapter/standard/capability/pagination/operation/paginate/offset.rb +66 -0
- data/lib/apiwork/adapter/standard/capability/pagination/operation/paginate.rb +24 -0
- data/lib/apiwork/adapter/standard/capability/pagination/operation.rb +24 -0
- data/lib/apiwork/adapter/standard/capability/pagination.rb +21 -0
- data/lib/apiwork/adapter/standard/capability/sorting/api_builder.rb +19 -0
- data/lib/apiwork/adapter/standard/capability/sorting/contract_builder.rb +84 -0
- data/lib/apiwork/adapter/standard/capability/sorting/operation/sort.rb +83 -0
- data/lib/apiwork/adapter/standard/capability/sorting/operation.rb +22 -0
- data/lib/apiwork/adapter/standard/capability/sorting.rb +17 -0
- data/lib/apiwork/adapter/standard/capability/writing/constants.rb +15 -0
- data/lib/apiwork/adapter/standard/capability/writing/contract_builder.rb +253 -0
- data/lib/apiwork/adapter/standard/capability/writing/operation/issue_mapper.rb +210 -0
- data/lib/apiwork/adapter/standard/capability/writing/operation.rb +32 -0
- data/lib/apiwork/adapter/standard/capability/writing/request_transformer.rb +37 -0
- data/lib/apiwork/adapter/standard/capability/writing.rb +17 -0
- data/lib/apiwork/adapter/standard/includes_resolver.rb +106 -0
- data/lib/apiwork/adapter/standard.rb +22 -0
- data/lib/apiwork/adapter/wrapper/base.rb +70 -0
- data/lib/apiwork/adapter/wrapper/collection/base.rb +60 -0
- data/lib/apiwork/adapter/wrapper/collection/default.rb +47 -0
- data/lib/apiwork/adapter/wrapper/error/base.rb +30 -0
- data/lib/apiwork/adapter/wrapper/error/default.rb +34 -0
- data/lib/apiwork/adapter/wrapper/member/base.rb +58 -0
- data/lib/apiwork/adapter/wrapper/member/default.rb +40 -0
- data/lib/apiwork/adapter/wrapper/shape.rb +203 -0
- data/lib/apiwork/adapter.rb +50 -0
- data/lib/apiwork/api/base.rb +802 -0
- data/lib/apiwork/api/element.rb +110 -0
- data/lib/apiwork/api/enum_registry/definition.rb +51 -0
- data/lib/apiwork/api/enum_registry.rb +98 -0
- data/lib/apiwork/api/info/contact.rb +67 -0
- data/lib/apiwork/api/info/license.rb +50 -0
- data/lib/apiwork/api/info/server.rb +50 -0
- data/lib/apiwork/api/info.rb +221 -0
- data/lib/apiwork/api/object.rb +235 -0
- data/lib/apiwork/api/registry.rb +33 -0
- data/lib/apiwork/api/representation_registry.rb +76 -0
- data/lib/apiwork/api/resource/action.rb +41 -0
- data/lib/apiwork/api/resource.rb +648 -0
- data/lib/apiwork/api/router.rb +104 -0
- data/lib/apiwork/api/type_registry/definition.rb +117 -0
- data/lib/apiwork/api/type_registry.rb +99 -0
- data/lib/apiwork/api/union.rb +49 -0
- data/lib/apiwork/api.rb +85 -0
- data/lib/apiwork/configurable.rb +71 -0
- data/lib/apiwork/configuration/option.rb +125 -0
- data/lib/apiwork/configuration/validatable.rb +25 -0
- data/lib/apiwork/configuration.rb +95 -0
- data/lib/apiwork/configuration_error.rb +6 -0
- data/lib/apiwork/constraint_error.rb +20 -0
- data/lib/apiwork/contract/action/request.rb +79 -0
- data/lib/apiwork/contract/action/response.rb +87 -0
- data/lib/apiwork/contract/action.rb +258 -0
- data/lib/apiwork/contract/base.rb +714 -0
- data/lib/apiwork/contract/element.rb +130 -0
- data/lib/apiwork/contract/object/coercer.rb +194 -0
- data/lib/apiwork/contract/object/deserializer.rb +101 -0
- data/lib/apiwork/contract/object/transformer.rb +95 -0
- data/lib/apiwork/contract/object/validator/result.rb +27 -0
- data/lib/apiwork/contract/object/validator.rb +734 -0
- data/lib/apiwork/contract/object.rb +566 -0
- data/lib/apiwork/contract/request_parser/result.rb +25 -0
- data/lib/apiwork/contract/request_parser.rb +72 -0
- data/lib/apiwork/contract/response_parser/result.rb +25 -0
- data/lib/apiwork/contract/response_parser.rb +35 -0
- data/lib/apiwork/contract/union.rb +56 -0
- data/lib/apiwork/contract_error.rb +9 -0
- data/lib/apiwork/controller.rb +300 -0
- data/lib/apiwork/domain_error.rb +13 -0
- data/lib/apiwork/element.rb +386 -0
- data/lib/apiwork/engine.rb +20 -0
- data/lib/apiwork/error.rb +6 -0
- data/lib/apiwork/error_code/definition.rb +63 -0
- data/lib/apiwork/error_code/registry.rb +18 -0
- data/lib/apiwork/error_code.rb +132 -0
- data/lib/apiwork/export/base.rb +291 -0
- data/lib/apiwork/export/open_api.rb +600 -0
- data/lib/apiwork/export/pipeline/writer.rb +66 -0
- data/lib/apiwork/export/pipeline.rb +84 -0
- data/lib/apiwork/export/registry.rb +16 -0
- data/lib/apiwork/export/surface_resolver.rb +189 -0
- data/lib/apiwork/export/type_analysis.rb +170 -0
- data/lib/apiwork/export/type_script.rb +23 -0
- data/lib/apiwork/export/type_script_mapper.rb +349 -0
- data/lib/apiwork/export/zod.rb +39 -0
- data/lib/apiwork/export/zod_mapper.rb +421 -0
- data/lib/apiwork/export.rb +80 -0
- data/lib/apiwork/http_error.rb +16 -0
- data/lib/apiwork/introspection/action/request.rb +66 -0
- data/lib/apiwork/introspection/action/response.rb +57 -0
- data/lib/apiwork/introspection/action.rb +124 -0
- data/lib/apiwork/introspection/api/info/contact.rb +59 -0
- data/lib/apiwork/introspection/api/info/license.rb +49 -0
- data/lib/apiwork/introspection/api/info/server.rb +50 -0
- data/lib/apiwork/introspection/api/info.rb +107 -0
- data/lib/apiwork/introspection/api/resource.rb +83 -0
- data/lib/apiwork/introspection/api.rb +92 -0
- data/lib/apiwork/introspection/contract.rb +63 -0
- data/lib/apiwork/introspection/dump/action.rb +101 -0
- data/lib/apiwork/introspection/dump/api.rb +119 -0
- data/lib/apiwork/introspection/dump/contract.rb +129 -0
- data/lib/apiwork/introspection/dump/param.rb +486 -0
- data/lib/apiwork/introspection/dump/resource.rb +112 -0
- data/lib/apiwork/introspection/dump/type.rb +339 -0
- data/lib/apiwork/introspection/dump.rb +17 -0
- data/lib/apiwork/introspection/enum.rb +63 -0
- data/lib/apiwork/introspection/error_code.rb +44 -0
- data/lib/apiwork/introspection/param/array.rb +88 -0
- data/lib/apiwork/introspection/param/base.rb +285 -0
- data/lib/apiwork/introspection/param/binary.rb +73 -0
- data/lib/apiwork/introspection/param/boolean.rb +73 -0
- data/lib/apiwork/introspection/param/date.rb +73 -0
- data/lib/apiwork/introspection/param/date_time.rb +73 -0
- data/lib/apiwork/introspection/param/decimal.rb +121 -0
- data/lib/apiwork/introspection/param/integer.rb +131 -0
- data/lib/apiwork/introspection/param/literal.rb +45 -0
- data/lib/apiwork/introspection/param/number.rb +121 -0
- data/lib/apiwork/introspection/param/object.rb +59 -0
- data/lib/apiwork/introspection/param/reference.rb +45 -0
- data/lib/apiwork/introspection/param/string.rb +122 -0
- data/lib/apiwork/introspection/param/time.rb +73 -0
- data/lib/apiwork/introspection/param/union.rb +57 -0
- data/lib/apiwork/introspection/param/unknown.rb +26 -0
- data/lib/apiwork/introspection/param/uuid.rb +73 -0
- data/lib/apiwork/introspection/param.rb +31 -0
- data/lib/apiwork/introspection/type.rb +129 -0
- data/lib/apiwork/introspection.rb +28 -0
- data/lib/apiwork/issue.rb +80 -0
- data/lib/apiwork/json_pointer.rb +21 -0
- data/lib/apiwork/object.rb +1618 -0
- data/lib/apiwork/reference_generator.rb +638 -0
- data/lib/apiwork/registry.rb +56 -0
- data/lib/apiwork/representation/association.rb +391 -0
- data/lib/apiwork/representation/attribute.rb +335 -0
- data/lib/apiwork/representation/base.rb +819 -0
- data/lib/apiwork/representation/deserializer.rb +95 -0
- data/lib/apiwork/representation/element.rb +128 -0
- data/lib/apiwork/representation/inheritance.rb +78 -0
- data/lib/apiwork/representation/model_detector.rb +75 -0
- data/lib/apiwork/representation/root_key.rb +35 -0
- data/lib/apiwork/representation/serializer.rb +127 -0
- data/lib/apiwork/request.rb +79 -0
- data/lib/apiwork/response.rb +56 -0
- data/lib/apiwork/union.rb +102 -0
- data/lib/apiwork/version.rb +2 -2
- data/lib/apiwork.rb +61 -3
- data/lib/generators/apiwork/api_generator.rb +38 -0
- data/lib/generators/apiwork/contract_generator.rb +25 -0
- data/lib/generators/apiwork/install_generator.rb +27 -0
- data/lib/generators/apiwork/representation_generator.rb +25 -0
- data/lib/generators/apiwork/templates/api/api.rb.tt +4 -0
- data/lib/generators/apiwork/templates/contract/contract.rb.tt +6 -0
- data/lib/generators/apiwork/templates/install/application_contract.rb.tt +5 -0
- data/lib/generators/apiwork/templates/install/application_representation.rb.tt +5 -0
- data/lib/generators/apiwork/templates/representation/representation.rb.tt +6 -0
- data/lib/tasks/apiwork.rake +102 -0
- metadata +319 -19
- data/.rubocop.yml +0 -8
- data/sig/apiwork.rbs +0 -4
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Apiwork
|
|
4
|
+
module Introspection
|
|
5
|
+
module Param
|
|
6
|
+
# @api public
|
|
7
|
+
# UUID param representing universally unique identifier values.
|
|
8
|
+
#
|
|
9
|
+
# @example Basic usage
|
|
10
|
+
# param.type # => :uuid
|
|
11
|
+
# param.scalar? # => true
|
|
12
|
+
# param.uuid? # => true
|
|
13
|
+
#
|
|
14
|
+
# @example Capabilities
|
|
15
|
+
# param.formattable? # => false
|
|
16
|
+
#
|
|
17
|
+
# @example Enum
|
|
18
|
+
# if param.enum?
|
|
19
|
+
# param.enum # => ["550e8400-e29b-41d4-a716-446655440000"]
|
|
20
|
+
# param.enum_reference? # => false
|
|
21
|
+
# end
|
|
22
|
+
class UUID < Base
|
|
23
|
+
# @api public
|
|
24
|
+
# Whether this param is scalar.
|
|
25
|
+
#
|
|
26
|
+
# @return [Boolean]
|
|
27
|
+
def scalar?
|
|
28
|
+
true
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# @api public
|
|
32
|
+
# Whether this param has an enum.
|
|
33
|
+
#
|
|
34
|
+
# @return [Boolean]
|
|
35
|
+
def enum?
|
|
36
|
+
@dump[:enum].present?
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# @api public
|
|
40
|
+
# The enum for this param.
|
|
41
|
+
#
|
|
42
|
+
# @return [Array<String>, Symbol, nil]
|
|
43
|
+
def enum
|
|
44
|
+
@dump[:enum]
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# @api public
|
|
48
|
+
# Whether this param is an enum reference.
|
|
49
|
+
#
|
|
50
|
+
# @return [Boolean]
|
|
51
|
+
def enum_reference?
|
|
52
|
+
@dump[:enum].is_a?(Symbol)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# @api public
|
|
56
|
+
# Whether this param is a UUID.
|
|
57
|
+
#
|
|
58
|
+
# @return [Boolean]
|
|
59
|
+
def uuid?
|
|
60
|
+
true
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# @api public
|
|
64
|
+
# Whether this param is formattable.
|
|
65
|
+
#
|
|
66
|
+
# @return [Boolean]
|
|
67
|
+
def formattable?
|
|
68
|
+
false
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Apiwork
|
|
4
|
+
module Introspection
|
|
5
|
+
module Param
|
|
6
|
+
class << self
|
|
7
|
+
def build(dump)
|
|
8
|
+
case dump[:type]
|
|
9
|
+
when :string then String.new(dump)
|
|
10
|
+
when :integer then Integer.new(dump)
|
|
11
|
+
when :number then Number.new(dump)
|
|
12
|
+
when :decimal then Decimal.new(dump)
|
|
13
|
+
when :boolean then Boolean.new(dump)
|
|
14
|
+
when :datetime then DateTime.new(dump)
|
|
15
|
+
when :date then Date.new(dump)
|
|
16
|
+
when :time then Time.new(dump)
|
|
17
|
+
when :uuid then UUID.new(dump)
|
|
18
|
+
when :binary then Binary.new(dump)
|
|
19
|
+
when :unknown then Unknown.new(dump)
|
|
20
|
+
when :array then Array.new(dump)
|
|
21
|
+
when :object then Object.new(dump)
|
|
22
|
+
when :union then Union.new(dump)
|
|
23
|
+
when :literal then Literal.new(dump)
|
|
24
|
+
when :reference then Reference.new(dump)
|
|
25
|
+
else Unknown.new(dump)
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Apiwork
|
|
4
|
+
module Introspection
|
|
5
|
+
# @api public
|
|
6
|
+
# Wraps custom type definitions.
|
|
7
|
+
#
|
|
8
|
+
# Types can be objects (with shapes) or unions (with variants).
|
|
9
|
+
#
|
|
10
|
+
# @example Object type
|
|
11
|
+
# api.types[:address].object? # => true
|
|
12
|
+
# api.types[:address].shape[:city] # => Param for city field
|
|
13
|
+
#
|
|
14
|
+
# @example Union type
|
|
15
|
+
# api.types[:payment_method].union? # => true
|
|
16
|
+
# api.types[:payment_method].variants # => [Param, ...]
|
|
17
|
+
# api.types[:payment_method].discriminator # => :type
|
|
18
|
+
class Type
|
|
19
|
+
def initialize(dump)
|
|
20
|
+
@dump = dump
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# @api public
|
|
24
|
+
# The type for this type.
|
|
25
|
+
#
|
|
26
|
+
# @return [Symbol, nil]
|
|
27
|
+
def type
|
|
28
|
+
@dump[:type]
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# @api public
|
|
32
|
+
# Whether this type is an object.
|
|
33
|
+
#
|
|
34
|
+
# @return [Boolean]
|
|
35
|
+
def object?
|
|
36
|
+
type == :object
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# @api public
|
|
40
|
+
# Whether this type is a union.
|
|
41
|
+
#
|
|
42
|
+
# @return [Boolean]
|
|
43
|
+
def union?
|
|
44
|
+
type == :union
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# @api public
|
|
48
|
+
# The shape for this type.
|
|
49
|
+
#
|
|
50
|
+
# @return [Hash{Symbol => Param}]
|
|
51
|
+
def shape
|
|
52
|
+
@shape ||= @dump[:shape].transform_values { |dump| Param.build(dump) }
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# @api public
|
|
56
|
+
# The variants for this type.
|
|
57
|
+
#
|
|
58
|
+
# @return [Array<Param>]
|
|
59
|
+
def variants
|
|
60
|
+
@variants ||= @dump[:variants].map { |variant| Param.build(variant) }
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# @api public
|
|
64
|
+
# The discriminator for this type.
|
|
65
|
+
#
|
|
66
|
+
# @return [Symbol, nil]
|
|
67
|
+
def discriminator
|
|
68
|
+
@dump[:discriminator]
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# @api public
|
|
72
|
+
# The description for this type.
|
|
73
|
+
#
|
|
74
|
+
# @return [String, nil]
|
|
75
|
+
def description
|
|
76
|
+
@dump[:description]
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# @api public
|
|
80
|
+
# The extends for this type.
|
|
81
|
+
#
|
|
82
|
+
# @return [Array<Symbol>]
|
|
83
|
+
def extends
|
|
84
|
+
@dump[:extends]
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# @api public
|
|
88
|
+
# Whether this type extends other types.
|
|
89
|
+
#
|
|
90
|
+
# @return [Boolean]
|
|
91
|
+
def extends?
|
|
92
|
+
extends.any?
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# @api public
|
|
96
|
+
# The example for this type.
|
|
97
|
+
#
|
|
98
|
+
# @return [Object, nil]
|
|
99
|
+
def example
|
|
100
|
+
@dump[:example]
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
# @api public
|
|
104
|
+
# Whether this type is deprecated.
|
|
105
|
+
#
|
|
106
|
+
# @return [Boolean]
|
|
107
|
+
def deprecated?
|
|
108
|
+
@dump[:deprecated]
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
# @api public
|
|
112
|
+
# Converts this type to a hash.
|
|
113
|
+
#
|
|
114
|
+
# @return [Hash]
|
|
115
|
+
def to_h
|
|
116
|
+
{
|
|
117
|
+
deprecated: deprecated?,
|
|
118
|
+
description: description,
|
|
119
|
+
discriminator: discriminator,
|
|
120
|
+
example: example,
|
|
121
|
+
extends: extends,
|
|
122
|
+
shape: shape.transform_values(&:to_h),
|
|
123
|
+
type: type,
|
|
124
|
+
variants: variants.map(&:to_h),
|
|
125
|
+
}
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Apiwork
|
|
4
|
+
module Introspection
|
|
5
|
+
class << self
|
|
6
|
+
def api(api_class, locale: nil)
|
|
7
|
+
with_locale(locale) { API.new(Dump.api(api_class)) }
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def contract(contract_class, expand: false, locale: nil)
|
|
11
|
+
with_locale(locale) { Contract.new(Dump.contract(contract_class, expand:)) }
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
private
|
|
15
|
+
|
|
16
|
+
def with_locale(locale, &block)
|
|
17
|
+
return yield unless locale
|
|
18
|
+
|
|
19
|
+
unless I18n.available_locales.include?(locale)
|
|
20
|
+
raise ConfigurationError,
|
|
21
|
+
"locale must be one of #{I18n.available_locales.inspect}, got #{locale.inspect}"
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
I18n.with_locale(locale, &block)
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Apiwork
|
|
4
|
+
# @api public
|
|
5
|
+
# Represents a validation issue found during request parsing.
|
|
6
|
+
#
|
|
7
|
+
# Issues are returned when request parameters fail validation,
|
|
8
|
+
# coercion, or constraint checks. Access via `contract.issues`.
|
|
9
|
+
class Issue
|
|
10
|
+
# @!attribute [r] code
|
|
11
|
+
# @api public
|
|
12
|
+
# The code for this issue.
|
|
13
|
+
#
|
|
14
|
+
# @return [Symbol]
|
|
15
|
+
# @!attribute [r] detail
|
|
16
|
+
# @api public
|
|
17
|
+
# The detail for this issue.
|
|
18
|
+
#
|
|
19
|
+
# @return [String]
|
|
20
|
+
# @!attribute [r] meta
|
|
21
|
+
# @api public
|
|
22
|
+
# The meta for this issue.
|
|
23
|
+
#
|
|
24
|
+
# @return [Hash]
|
|
25
|
+
# @!attribute [r] path
|
|
26
|
+
# @api public
|
|
27
|
+
# The path for this issue.
|
|
28
|
+
#
|
|
29
|
+
# @return [Array<Symbol, Integer>]
|
|
30
|
+
attr_reader :code,
|
|
31
|
+
:detail,
|
|
32
|
+
:meta,
|
|
33
|
+
:path
|
|
34
|
+
|
|
35
|
+
def initialize(code, detail, meta: {}, path: [])
|
|
36
|
+
@code = code
|
|
37
|
+
@detail = detail
|
|
38
|
+
@path = path.map { |element| element.is_a?(Integer) ? element : element.to_sym }
|
|
39
|
+
@meta = meta
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# @api public
|
|
43
|
+
# The pointer for this issue.
|
|
44
|
+
#
|
|
45
|
+
# @return [String]
|
|
46
|
+
def pointer
|
|
47
|
+
@pointer ||= JSONPointer.new(*path).to_s
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# @api public
|
|
51
|
+
# Converts this issue to a hash.
|
|
52
|
+
#
|
|
53
|
+
# @return [Hash]
|
|
54
|
+
def to_h
|
|
55
|
+
{
|
|
56
|
+
code: code,
|
|
57
|
+
detail: detail,
|
|
58
|
+
meta: meta,
|
|
59
|
+
path: path.map(&:to_s),
|
|
60
|
+
pointer: pointer,
|
|
61
|
+
}
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# @api public
|
|
65
|
+
# Converts this issue to a hash for JSON serialization.
|
|
66
|
+
#
|
|
67
|
+
# @return [Hash]
|
|
68
|
+
def as_json
|
|
69
|
+
to_h
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# @api public
|
|
73
|
+
# Converts this issue to a string.
|
|
74
|
+
#
|
|
75
|
+
# @return [String]
|
|
76
|
+
def to_s
|
|
77
|
+
"[#{code}]#{path.any? ? " at #{pointer}" : ''} #{detail}"
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Apiwork
|
|
4
|
+
class JSONPointer
|
|
5
|
+
def initialize(*path)
|
|
6
|
+
@path = path
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def to_s
|
|
10
|
+
return '' if @path.empty?
|
|
11
|
+
|
|
12
|
+
"/#{@path.map { |component| escape(component.to_s) }.join('/')}"
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
private
|
|
16
|
+
|
|
17
|
+
def escape(component)
|
|
18
|
+
component.gsub('~', '~0').gsub('/', '~1')
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|